/*
*  Object %name    : %
*  State           :  %state%
*  Creation date   :  August 6, 2008
*  Last modified   :  %modify_time%
*/
/** @file
*  \brief A brief description of this module
*
*  \version SST_TST_ATP_MM.c#1:csrc:1
*  \author Sagit Ben Tsur
*  \remarks Copyright (C) 2008 by Discretix Technologies Ltd.
*           All Rights reserved
*/
/************* Include Files ***********************************/
#include "SST_TST.h"
#if TST_USE_SST_MM_MODULE
/************************ Defines ******************************/
/************************ Enums ********************************/
/************************ Typedefs *****************************/
/************************ Global Data **************************/
/************* Private function prototype **********************/
/************************ Public Functions *********************/
/****************************************************************/

/*****************************************************************************
* Function Name:                                                           
*  SST_TST_ATP_MM
*
* Inputs:
*  None
*
* Outputs:
*  DxError_t - Function error return
*
* Description:
*    Test the mode management set and get APIs and authenticator with mode
*
* Algorithm:
*    1. USER - Board: cold boot, PC: exit the ATP application.
*    2. USER - Start the ATP application and choose the mode management 0peration test.
*    3. Call SST_Terminate and SST_Init.
*    4. Call SST_MMGet and verify the SST is in privilege mode.
*    5. Call SST_SessionCreate.
*    6. Call SST_TransactionStart. 
*    7. Call SST_MMPrivAuthCreate to Create a privileged mode authenticator
*    8. Call SST_AuthenticatorAESSharedSecretCreate.
*    9. Call SST_AuthenticatorPasswordCreate - this Authenticator will be in user mode  - cleaner-authenticator.
*    10. Call SST_MMAuthSet and set to Privileged.
*    11. Call SST_DataInsert with the priv-authenticator as initial control authenticator.
*    12. Call SST_TransactionEnd.
*    13. Call SST_MMPriAuthOpen to open the priv-authenticator on the session.
*    14. Call SST_TransactionStart 
*    15 . Call SST_AuthenticatorBind with the data and aes-authenticator.
*    16. Call SST_AuthenticatorBind with the data and cleaner-authenticator.
*    17. Call SST_DataRead and verify the data is correct. 
*    18. Call SST_AuthenticationClose (priv).
*    19. Call SST_DataRead – FAIL
*    20. Call SST_TransactionEnd.
*    21. Call SST_MMSet and set the system to user mode.
*    22. Call SST_MMPrivAuthOpen to the priv-authenticator, verify the operation failed.
*    23. Call SST_AuthenticatorChallengeGet
*    24. Call CRYS_AES and Encrypt the data with the key fro the AES authenticator
*    25. Call SST_AuthenticationOpen to the aes-authenticator, verify the operation failed.
*    26. Call SST_SessionDelete.
*    27. Call SST_Terminate.
*    28. Call SST_Init
*    29.    #ifndef DX_CC5_SEP_PLAT
*         Call SST_MMSet with user mode
*        #endif // PC
*    30. Call SST_MMGet and verify the SST is in user mode.
*    31. Call SST_SessionCreate.
*    32. Call SST_AuthenticationOpen to the cleaner-authenticator.
*    33. Call SST_TransactionStart 
*    34. Call SST_DataDelete to delete the data object.
*    35. Close the cleaner authenticator.
*    35  Call SST_AuthenticatorDelete to all the authenticators
*    36. Call SST_SessionDelete
*    37. Call SST_TransactionEnd
*******************************************************************************/     
DxError_t SST_TST_ATP_MM ( void )
{
    DxChar             * TestName = "ATP test SST mode management";
    DxChar             * pass = "1234";
    SSTSessionId_t     TST_SessionId;
    SSTTxnId_t         TST_TransactionId;
    SSTMode_t          TST_SSTState;
    SSTHandle_t        TST_AESAuthHandle,TST_PrivAuthHandle,TST_DataHandle,TST_InitialCtrlAuth, TST_CleanAuthHandle;
    SSTDataType_t      TST_DataType = TST_DATA_OBJECT;
    SSTChallengeId_t   TST_ChallengeId;
    static DxBool_t    TST_FirstRun  = DX_FALSE;
  DxError_t       TST_Status = DX_FAILURE;
   
   #ifndef DX_CC5_SEP_PLAT 
   if(!TST_FirstRun)
      TST_FirstRun = DX_TRUE;
    else
    {
      ATP_LOG_TST_PRINT((SST_TST_MSG,"In order to run this test again a cold boot must take place - please restart the application\n"));
      return TST_Status;
    }
   #endif
    
    TST_InitialCtrlAuth.objId = SST_CLOSE_AUTH_HANDLE;
    TST_InitialCtrlAuth.objDigest = 0;
    
    ATP_LOG_TST_PRINT((SST_TST_MSG," ****************************************************** \n"));
    ATP_LOG_TST_PRINT((SST_TST_MSG," ** SST_TST_ATP_MM Tests ****************************** \n"));
    ATP_LOG_TST_PRINT((SST_TST_MSG," ****************************************************** \n \n"));
 

    /*3.Call SST_Terminate and SST_Init. */
     TST_Status = SST_Terminate();
    
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_Terminate",
                                          TestName,
                                          TestName);

  

    TST_Status = SST_Init((DxNvsMemoryId_t)TST_MainDBFileHandle,
                          (DxNvsMemoryId_t)TST_SecondaryDBFileHandle,
                          DX_NULL,
                          TST_Workspace,
                          TST_WorkspaceSizeInBytes);

   TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_Init",
                                          TestName,
                                          TestName);


    /*4. Call SST_MMGet and verify the SST is in privilege mode.*/
    TST_Status = SST_MMGet(&TST_SSTState);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_MMGet",
                                          TestName,
                                          TestName);


    if(TST_SSTState != SST_MODE_PRIVILEGED)
      TST_Status  = TESTFAIL;
    else
      TST_Status  = TESTPASS;




     /* 5.Call SST_SessionCreate */
    /*---------------------------*/
      TST_Status = SST_SessionCreate(&TST_SessionId);

      TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_SessionCreate",
                   TestName,
                   TestName);


    /*6. Call SST_TransactionStart*/
    /*----------------------------*/
    TST_Status = SST_TransactionStart(&TST_TransactionId);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_TransactionStart",
                                          TestName,
                                          TestName);


    /*7. Call SST_MMPriAuthCreate to Create a privileged mode authenticator*/
    TST_Status = SST_MMPrivAuthCreate(TST_TransactionId,
                                     TST_SessionId,
                                     &TST_PrivAuthHandle,
                                     TST_Workspace,
                                     TST_WorkspaceSizeInBytes);

    
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_MMPrivAuthCreate",
                                          TestName,
                                          TestName);


    TST_AESAuthHandle.objId = SST_HANDLE_RANDOM_GENERATE;

    /* 8.Call SST_AuthenticatorAESSharedSecretCreate*/
    TST_Status = SST_AuthenticatorAESSharedSecretCreate(TST_TransactionId,
                                                       TST_ATP_AesKeyAuthObjectTestData[0].TST_AesKey,
                                                       SST_KEY_TYPE_AES_128_BIT,
                                                       &TST_AESAuthHandle,
                                                       TST_Workspace,
                                                       TST_WorkspaceSizeInBytes);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_AuthenticatorAESSharedSecretCreate",
                                          TestName,
                                          TestName);
 

    TST_CleanAuthHandle.objId = SST_HANDLE_RANDOM_GENERATE;

   /* 9.Call SST_AuthenticatorPasswordCreate - this Authenticator will be in user mode - cleaner-authenticator.*/
   TST_Status = SST_AuthenticatorPasswordCreate(TST_TransactionId,
                                               TST_SessionId,
                                               pass,
                                               sizeof(pass),
                                               1,
                                               TST_InitialCtrlAuth,
                                               &TST_CleanAuthHandle,
                                               TST_Workspace,
                                               TST_WorkspaceSizeInBytes);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_AuthenticatorPasswordCreate",
                                          TestName,
                                          TestName);
    

    /*10. Call SST_MMAuthSet and set to Privileged.*/
    TST_Status = SST_MMAuthSet(TST_TransactionId,  
                              TST_AESAuthHandle,
                              SST_MODE_PRIVILEGED,                        
                              TST_Workspace,
                              TST_WorkspaceSizeInBytes);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_MMAuthSet",
                                          TestName,
                                          TestName);
   

  
   /* 11. Call SST_DataInsert with the priv-authenticator as initial control authenticator. */
    TST_Status = SST_DataInsert(TST_TransactionId,
                               TST_SessionId, 
                               TST_PrivAuthHandle,
                               TST_ATP_DataOpTestData[0].TST_Data,
                               TST_ATP_DataOpTestData[0].TST_DataSize,
                               DX_TRUE,
                               TST_DataType,
                               &TST_DataHandle,
                               TST_Workspace,
                               TST_WorkspaceSizeInBytes);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_DataInsert",
                                          TestName,
                                          TestName);
    

    /*12. Call SST_TransactionEnd*/
    TST_Status = SST_TransactionEnd(TST_TransactionId,DX_TRUE,TST_Workspace,TST_WorkspaceSizeInBytes);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_TransactionEnd",
                                          TestName,
                                          TestName);
    

    /*13 Call SST_MMPriAuthOpen to open the priv-authenticator on the session*/
     TST_Status = SST_MMPrivAuthOpen(TST_SessionId,TST_PrivAuthHandle,TST_Workspace,TST_WorkspaceSizeInBytes);
     TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_MMPriAuthOpen",
                                           TestName,
                                           TestName);
     

     /*14. Call SST_TransactionStart*/
    TST_Status = SST_TransactionStart(&TST_TransactionId);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_TransactionStart",
                                          TestName,
                                          TestName);
    

    /*15  Call SST_AuthenticatorBind with the data and aes-authenticator.*/
    TST_Status = SST_AuthenticatorBind(TST_TransactionId,
                                      TST_SessionId,
                                      TST_DataHandle,
                                      TST_AESAuthHandle,
                                      SST_PERMISSION_READ_ONLY,
                                      TST_Workspace,
                                      TST_WorkspaceSizeInBytes);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_AuthenticatorBind",
                                          TestName,
                                          TestName);
    

   /*16. Call SST_AuthenticatorBind with the data and cleaner-authenticator.*/
    TST_Status = SST_AuthenticatorBind(TST_TransactionId,
                                      TST_SessionId,
                                      TST_DataHandle,
                                      TST_CleanAuthHandle,
                                      SST_PERMISSION_CONTROL,
                                      TST_Workspace,
                                      TST_WorkspaceSizeInBytes);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_AuthenticatorBind",
                                          TestName,
                                          TestName);
    

     /*17. Call SST_DataRead and verify the data is correct.*/
    TST_Status = SST_DataRead(TST_SessionId,
                             TST_DataHandle,
                             0,
                             TST_ATP_BindingWritingPermissionsTestData[0].TST_OutputData,
                             &TST_ATP_DataOpTestData[0].TST_DataSize,
                             TST_Workspace,
                             TST_WorkspaceSizeInBytes);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_DataRead",
                                          TestName,
                                          TestName);
   

    /* Compare the retrieved data to the original */
    if(!DX_VOS_MemCmp(TST_ATP_DataOpTestData[0].TST_Data,
                      TST_ATP_BindingWritingPermissionsTestData[0].TST_OutputData,
                      TST_ATP_DataOpTestData[0].TST_DataSize))
      TST_Status = TESTPASS; /*Data Buffers are the same*/
    else
      TST_Status = TESTFAIL; /*Data Buffers are different*/

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"DX_VOS_MemCmp",
                                          TestName,
                                          TestName);
    

    /*18. Call SST_AuthenticationClose (priv).*/
    TST_Status = SST_AuthenticationClose(TST_SessionId,TST_PrivAuthHandle);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_AuthenticationClose priv",
                                          TestName,
                                          TestName);
    

    /*19. Call SST_DataRead – FAIL*/
    TST_Status = SST_DataRead(TST_SessionId,
                             TST_DataHandle,
                             0,
                             TST_ATP_BindingWritingPermissionsTestData[0].TST_OutputData,
                             &TST_ATP_DataOpTestData[0].TST_DataSize,
                             TST_Workspace,
                             TST_WorkspaceSizeInBytes);

    if(TST_Status == SST_RC_ERROR_ACCESS_DENIED)
      TST_Status = TESTPASS;
    else 
      TST_Status = TESTFAIL;

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_DataRead (FAIL)",
                                          TestName,
                                          TestName);
    

   
    /*20. Call SST_TransactionEnd.*/
    TST_Status = SST_TransactionEnd(TST_TransactionId,DX_TRUE,TST_Workspace,TST_WorkspaceSizeInBytes);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_TransactionEnd",
                                          TestName,
                                          TestName);

    /*21. Call SST_MMSystemSet and set the system to user mode.*/
    TST_Status = SST_MMSet(SST_MODE_USER);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_MMSet - SST_STATE_MODE_USER",
                                          TestName,
                                          TestName);
  

    /*22. Call SST_MMPrivAuthOpen to the priv-authenticator, verify the operation failed.*/
    TST_Status = SST_MMPrivAuthOpen(TST_SessionId,TST_PrivAuthHandle,TST_Workspace, TST_WorkspaceSizeInBytes);

     if(TST_Status == SST_RC_ERROR_MODE_ILLEGAL)
      TST_Status = TESTPASS;
    else 
      TST_Status = TESTFAIL;

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_MMPrivAuthOpen  (FAIL)",
                                          TestName,
                                          TestName);
    

    /* 23. Call SST_AuthenticatorChallengeGet*/
    TST_Status = SST_AuthenticatorChallengeGet(TST_ATP_AesKeyAuthObjectTestData[0].TST_ChallengeBuff,
                                              TST_ATP_AesKeyAuthObjectTestData[0].TST_ChallengeBuffSize,  
                                              &TST_ChallengeId);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_AuthenticatorChallengeGet",
                                          TestName,
                                          TestName);
    

    /* 24. Call CRYS_AES and Encrypt the data with the key fro the AES authenticator */
    TST_Status = CRYS_AES(DX_NULL,
                         TST_ATP_AesKeyAuthObjectTestData[0].TST_AesKey,
                         CRYS_AES_Key128BitSize,
                         CRYS_AES_Encrypt,
                         CRYS_AES_ECB_mode,
                         TST_ATP_AesKeyAuthObjectTestData[0].TST_ChallengeBuff,
                         TST_ATP_AesKeyAuthObjectTestData[0].TST_ChallengeBuffSize,
                         TST_ATP_AesKeyAuthObjectTestData[0].TST_EncChallengeBuff);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"CRYS_AES",
                                          TestName,
                                          TestName);

    /*25. Call SST_AuthenticationOpen to the aes-authenticator, verify the operation failed.*/
    TST_Status = SST_AuthenticationOpen(TST_SessionId,
                                       TST_AESAuthHandle,
                                       TST_ATP_AesKeyAuthObjectTestData[0].TST_EncChallengeBuff,
                                       TST_ATP_AesKeyAuthObjectTestData[0].TST_EncChallengeBuffSize,
                                       TST_ChallengeId,
                                       TST_Workspace,
                                       TST_WorkspaceSizeInBytes);

    if(TST_Status == SST_RC_ERROR_MODE_ILLEGAL)
      TST_Status = TESTPASS;
    else 
      TST_Status = TESTFAIL;

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_AuthenticationOpen  (FAIL)",
                 TestName,
                 TestName);


    /*26. Call SST_SessionDelete.*/
    TST_Status = SST_SessionDelete(TST_SessionId);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_SessionDelete",
                                          TestName,
                                          TestName);


    /*27. Call SST_Terminate.*/
    TST_Status = SST_Terminate();
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_Terminate",
                                          TestName,
                                          TestName);


    /*28. Call SST_Init*/
    TST_Status = SST_Init((DxNvsMemoryId_t)TST_MainDBFileHandle,
                         (DxNvsMemoryId_t)TST_SecondaryDBFileHandle,
                          DX_NULL,
                          TST_Workspace,
                          TST_WorkspaceSizeInBytes);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_Init",
                                          TestName,
                                          TestName);
    

    #ifndef DX_CC5_SEP_PLAT
   /*29. Call SST_MMSet with user mode*/
    TST_Status = SST_MMSet(SST_MODE_USER);
   TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_MMSet",
                                          TestName,
                                          TestName);
 
    #endif
    /*30. Call SST_MMGet and verify the SST is in user mode.*/
    TST_Status = SST_MMGet(&TST_SSTState);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_MMGet",
                                           TestName,
                                           TestName);

    if(TST_SSTState == SST_MODE_USER)
      TST_Status = TESTPASS;
    else 
      TST_Status = TESTFAIL;

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"verify the SST is in user mode",
                                          TestName,
                                          TestName);
  
    /* 31. Call SST_SessionCreate.*/
    TST_Status = SST_SessionCreate(&TST_SessionId);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_SessionCreate",
                                          TestName,
                                          TestName);
  

    /* 32. Call SST_AuthenticationOpen to the cleaner-authenticator.*/
    TST_Status = SST_AuthenticationOpen(TST_SessionId,
                                       TST_CleanAuthHandle,
                                       pass,
                                       sizeof(pass),
                                       TST_NO_CHALLENGE,
                                       TST_Workspace,
                                       TST_WorkspaceSizeInBytes);


    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_AuthenticationOpen cleaner-authenticator)",
                                          TestName,
                                          TestName);
   

    /* 33. Call SST_TransactionStart */
    TST_Status = SST_TransactionStart(&TST_TransactionId);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_TransactionStart",
                                          TestName,
                                          TestName);
    

    /* 34. Call SST_DataDelete to delete the data object.*/
    TST_Status = SST_DataDelete(TST_TransactionId,
                               TST_SessionId,
                               TST_DataHandle,
                               TST_Workspace,
                               TST_WorkspaceSizeInBytes);

    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_DataDelete",
                                          TestName,
                                          TestName);
    

     /*35. Close the cleaner authenticator*/
    TST_Status =  SST_AuthenticationClose(TST_SessionId,TST_CleanAuthHandle);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_AuthenticationClose cleaner authenticator",
                                          TestName,
                                          TestName);
    

    /* 36. Call SST_AuthenticatorDelete to all the authenticators*/
    TST_Status = SST_AuthenticatorDelete(TST_TransactionId,TST_AESAuthHandle);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_AuthenticatorDelete AES authenticator",
                                          TestName,
                                          TestName);
    

    TST_Status = SST_AuthenticatorDelete(TST_TransactionId,TST_PrivAuthHandle);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_AuthenticatorDelete Priv authenticator",
                                          TestName,
                                          TestName);
    

    /* 37. Call SST_SessionDelete*/
    TST_Status = SST_SessionDelete(TST_SessionId);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_SessionDelete",
                                          TestName,
                                          TestName);
    
    /* 38. Call SST_TransactionEnd*/ 
    TST_Status = SST_TransactionEnd(TST_TransactionId,DX_TRUE,TST_Workspace,TST_WorkspaceSizeInBytes);
    TST_ATP_CHECK_ERROR_RETURN(TST_Status,"SST_TransactionEnd",
                                          TestName,
                                          TestName);
    return TST_Status;

EXIT_ON_ERROR:  
    return DX_FAILURE;  
}

#endif
