/*! \file 
**********************************************************************************
*Title:                        Discretix OMA DRM v2 Toolkit source file
*
* Filename:                     Toolkit, Certificate Handling
*
* Project, Target, subsystem:   Toolkit, OMA DRM
* 
* Created:                      02.04.2008
*
* Modified:                     02.04.2008
*
* \Author                       Ira Boguslavsky
*
* \Remarks
*           Copyright (C) 2007 by Discretix Technologies Ltd. All Rights reserved.
**********************************************************************************/

DxError_t TLK_CERT_1667_ChainValidationInit(     TLK_CERT_1667_ContextObj_t       *contextObject_ptr)
{
    DxError_t    error        = TLK_CERT_RC_OK;
    DxUint32_t   sramOffset   = TLK_CERT_START_OFFSET;   		/*offset into SRAM*/
    DxUint32_t   contObjSMPhy;
    DxUint32_t   contObjSMVirt;


    DxUint32_t   paramInBuffer [DX_1_WORD_PARAMS +        /*op code*/
                                DX_1_WORD_PARAMS +		  /*contextObject_ptr*/		/*buffSizeInBytes*/
                                DX_1_WORD_PARAMS];									/*buff_ptr*/


    DxUint32_t   paramOutBuffer[sizeof(TLK_CERT_1667_ContextObj_t)]; /*contextObject_ptr*/

    /************************************************************************/
    /*  Lock access to SEP                                                  */
    /************************************************************************/
    SEPDriver_Lock();

    /************************************************************************/
    /*  Address Conversion                                                  */
    /************************************************************************/    
    error = SEPDriver_AllocateDataPoolMemory(  (DxUint8_t*)contextObject_ptr, 
                                                sizeof(TLK_CERT_1667_ContextObj_t), 
                                                &contObjSMPhy, 
                                                &contObjSMVirt);
    TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

    error = SEPDriver_WriteToDataPoolMemory(  contObjSMVirt, 
                                                (DxUint8_t*)contextObject_ptr, 
                                                sizeof(TLK_CERT_1667_ContextObj_t));
    TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

    /* Check input parameters */
    if (TLK_CERT_IS_NULL_PARAM( contextObject_ptr))
    {
        return TLK_CERT_RC_ERROR_API_NULL_POINTER;
    }

    /************************************************************************/
    /* Start sending message to SeP                                         */
    /************************************************************************/
    SEPDriver_StartMessage(&sramOffset);

    paramInBuffer[0] = TLK_CERT_1667_CHAIN_VALIDATION_INIT_MSG_OP_CODE;
    paramInBuffer[1] = sizeof(TLK_CERT_1667_ContextObj_t);
    paramInBuffer[2] = contObjSMPhy;

    /* Send constant part */
    error = SEPDriver_WriteParamater((DxUint32_t)paramInBuffer,
                                      sizeof(DxUint32_t) * DX_3_WORDS_PARAMS,
                                      sizeof(DxUint32_t) * DX_3_WORDS_PARAMS,
                                      &sramOffset,
                                      DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* End message                                                          */
    /************************************************************************/
    SEPDriver_EndMessage(sramOffset);

    /************************************************************************/
    /* Wait for the response                                                */
    /************************************************************************/
    error = SEPDriver_POLL_FOR_REPONSE();
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* Start reading message from the SEP                                   */
    /************************************************************************/
    /* Start the message */
    error = SEPDriver_StartIncomingMessage(&sramOffset);
    if(error)
    {
        goto end_function_unlock;
    }
    /* Read opcode + status  */
    error = SEPDriver_ReadParamater((DxUint32_t)paramOutBuffer,
                                    sizeof(DxUint32_t) * 2,
                                    sizeof(DxUint32_t) * 2,
                                    &sramOffset ,
                                    DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /* check the opcode */
    if(paramOutBuffer[0] != TLK_CERT_CHAIN_VALIDATION_INIT_MSG_OP_CODE)
    {
        error = DX_WRONG_OPCODE_FROM_SEP_ERR;
        goto end_function_unlock;
    }

    /* check the status */
    if(paramOutBuffer[1] != TLK_CERT_RC_OK)
    {
        error = paramOutBuffer[1];
        goto end_function_unlock;
    }

    error = SEPDriver_ReadFromDataPoolMemory(contObjSMVirt,
        (DxUint8_t*)contextObject_ptr,
        sizeof(TLK_CERT_1667_ContextObj_t));


    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

end_function_unlock:   
    /* lock access to the SEP */
    SEPDriver_Unlock();

    return error;
}

DxError_t TLK_CERT_1667_ChainValidationProcess(   const     TLK_CERT_Buffer_t                   *prevCertificate_ptr,
                                                  const     TLK_CERT_Buffer_t                   *currCertificate_ptr, 
                                                            TLK_CERT_1667_ContextObj_t          *contextObject_ptr,
                                                            TLK_CERT_1667_AuthAction_t           authAction,
                                                            DxUint8_t                           *workspace_ptr,
                                                  const     DxUint32_t                           workspaceSizeInBytes)
{
    DxError_t    error        = TLK_CERT_RC_OK;
    DxUint32_t   sramOffset   = TLK_CERT_START_OFFSET;   /*offset into SRAM*/
    DxUint32_t   prevCertSMPhy;
    DxUint32_t   prevCertSMVirt;
    DxUint32_t   currCertSMPhy;
    DxUint32_t   currCertSMVirt;
    DxUint32_t   contObjSMPhy;
    DxUint32_t   contObjSMVirt;

#ifdef DX_NO_TLK_SCLK_SUPPORT
    DxUint32_t servClkDesc;
#endif

    DxUint32_t   paramInBuffer [DX_1_WORD_PARAMS +       /*op code*/
                                DX_1_WORD_PARAMS +       /*prevCertificate_ptr*/    /*buffSizeInBytes*/
                                DX_1_WORD_PARAMS +                                  /*buff_ptr*/
                                DX_1_WORD_PARAMS +       /*currCertificate_ptr*/    /*buffSizeInBytes*/
                                DX_1_WORD_PARAMS +                                  /*buff_ptr*/
                                DX_1_WORD_PARAMS +      /*contextObject_ptr*/      /*buffSizeInBytes*/
                                DX_1_WORD_PARAMS +                                 /*buff_ptr*/
                                DX_1_WORD_PARAMS];      /*authAction*/

    DxUint32_t   paramOutBuffer[DX_2_WORDS_PARAMS]; 


    /* Check input parameters */
    if (TLK_CERT_IS_NULL_3PARAMS( prevCertificate_ptr,
        currCertificate_ptr,
        contextObject_ptr))
    {
        return TLK_CERT_RC_ERROR_API_NULL_POINTER;
    }

#ifndef DX_NO_TLK_SCLK_SUPPORT
    if (TLK_CERT_IS_NULL_PARAM(servClkDesc_ptr))
    {
        return TLK_CERT_RC_ERROR_API_NULL_POINTER;
    }
#endif

    /************************************************************************/
    /*  Lock access to SEP                                                  */
    /************************************************************************/
    SEPDriver_Lock();

    /************************************************************************/
    /*  Address Conversion                                                  */
    /************************************************************************/
    /* Allocate memory for the priv certificate if it is not NULL */    
    if (prevCertificate_ptr->buff_ptr!=DX_NULL)
    {

        error = SEPDriver_AllocateDataPoolMemory(  (DxUint8_t*)(prevCertificate_ptr->buff_ptr), 
                                                        DX_ALIGN_TO_WORD(prevCertificate_ptr->buffSizeInBytes), 
                                                        &prevCertSMPhy, 
                                                        &prevCertSMVirt);
        TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

        error = SEPDriver_WriteToDataPoolMemory(  prevCertSMVirt, 
                                                    (DxUint8_t*)prevCertificate_ptr->buff_ptr, 
                                                    prevCertificate_ptr->buffSizeInBytes);
        TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;
    }
    else
    {
        prevCertSMPhy = DX_NULL;
        prevCertSMVirt = DX_NULL;
    }

    /* Allocate memory for the current certificate */ 
    error = SEPDriver_AllocateDataPoolMemory(  currCertificate_ptr->buff_ptr, 
                                                DX_ALIGN_TO_WORD(currCertificate_ptr->buffSizeInBytes), 
                                                &currCertSMPhy, 
                                                &currCertSMVirt);
    TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

    error = SEPDriver_WriteToDataPoolMemory(  currCertSMVirt, 
                                                (DxUint8_t*)currCertificate_ptr->buff_ptr, 
                                                currCertificate_ptr->buffSizeInBytes);
    TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

    /* Allocate memory for the context object */ 
    error = SEPDriver_AllocateDataPoolMemory(  (DxUint8_t*)contextObject_ptr, 
                                                sizeof(TLK_CERT_1667_ContextObj_t), 
                                                &contObjSMPhy, 
                                                &contObjSMVirt);
    TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

    error = SEPDriver_WriteToDataPoolMemory(    contObjSMVirt, 
                                                (DxUint8_t*)contextObject_ptr, 
                                                sizeof(TLK_CERT_1667_ContextObj_t));
    TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

    /************************************************************************/
    /* Start sending message to SeP                                         */
    /************************************************************************/
    SEPDriver_StartMessage(&sramOffset);

    paramInBuffer[0] = TLK_CERT_1667_CHAIN_VALIDATION_PROCESS_MSG_OP_CODE;
    if (prevCertificate_ptr->buff_ptr!=DX_NULL)
    {
        paramInBuffer[1] = prevCertificate_ptr->buffSizeInBytes;
        paramInBuffer[2] = prevCertSMPhy;
    }
    else
    {
        paramInBuffer[1] = 0;
        paramInBuffer[2] = 0;
    }
    paramInBuffer[3] = currCertificate_ptr->buffSizeInBytes;
    paramInBuffer[4] = currCertSMPhy;
    paramInBuffer[5] = sizeof(TLK_CERT_1667_ContextObj_t);
    paramInBuffer[6] = contObjSMPhy;
    paramInBuffer[7] = authAction;

    /* Send constant part */
    error = SEPDriver_WriteParamater(   (DxUint32_t)paramInBuffer,
                                        sizeof(DxUint32_t) * DX_8_WORDS_PARAMS,
                                        sizeof(DxUint32_t) * DX_8_WORDS_PARAMS,
                                        &sramOffset,
                                        DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* End message                                                          */
    /************************************************************************/
    SEPDriver_EndMessage(sramOffset);

    /************************************************************************/
    /* Wait for the response                                                */
    /************************************************************************/
    error = SEPDriver_POLL_FOR_REPONSE();
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* Start reading message from the SEP                                   */
    /************************************************************************/
    /* Start the message */
    error = SEPDriver_StartIncomingMessage(&sramOffset);
    if(error)
    {
        goto end_function_unlock;
    }
    /* Read opcode + status  */
    error = SEPDriver_ReadParamater((DxUint32_t)paramOutBuffer,
                                    sizeof(DxUint32_t) * 2,
                                    sizeof(DxUint32_t) * 2,
                                    &sramOffset ,
                                    DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /* check the opcode */
    if(paramOutBuffer[0] != TLK_CERT_CHAIN_VALIDATION_PROCESS_MSG_OP_CODE)
    {
        error = DX_WRONG_OPCODE_FROM_SEP_ERR;
        goto end_function_unlock;
    }

    /* check the status */
    if(paramOutBuffer[1] != TLK_CERT_RC_OK)
    {
        error = paramOutBuffer[1];
        goto end_function_unlock;
    }

    /* Get contextObject_ptr */
    error = SEPDriver_ReadFromDataPoolMemory(   contObjSMVirt,
                                                (DxUint8_t*)contextObject_ptr,
                                                sizeof(TLK_CERT_1667_ContextObj_t));

    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /* Update context object base address => must be equal to prev, because in the 
    next function call this certificate will be prev */

    contextObject_ptr->certificateBaseAddress = (prevCertSMPhy&0x00FFFFFF)|0xA0000000;

end_function_unlock:   
    /* lock access to the SEP */
    SEPDriver_Unlock();

    return error;
}

DxError_t TLK_CERT_1667_ChainValidationTerminate(       TLK_CERT_1667_ContextObj_t       *contextObject_ptr,
                                                        TLK_CERT_1667_CPVO_t             *cvpoObject_ptr)
{
    DxError_t    error        = TLK_CERT_RC_OK;
    DxUint32_t   sramOffset   = TLK_CERT_START_OFFSET;   /*offset into SRAM*/
    DxUint32_t   contObjSMPhy;
    DxUint32_t   contObjSMVirt;
    DxUint32_t   cvpoSMPhy;
    DxUint32_t   cvpoSMVirt;
    DxUint32_t   paramInBuffer [DX_1_WORD_PARAMS +       /*op code*/
                                DX_1_WORD_PARAMS +       /*contextObject_ptr*/  
                                DX_1_WORD_PARAMS];       /*cvpoObject_ptr*/    

    DxUint32_t   paramOutBuffer[DX_2_WORDS_PARAMS]; /*contextObject_ptr*/


    /* Check input parameters */
    if (TLK_CERT_IS_NULL_2PARAMS( cvpoObject_ptr,
        contextObject_ptr))
    {
        return TLK_CERT_RC_ERROR_API_NULL_POINTER;
    }

    /************************************************************************/
    /*  Lock access to SEP                                                  */
    /************************************************************************/
    SEPDriver_Lock();

    /************************************************************************/
    /*  Address Conversion                                                  */
    /************************************************************************/
    error = SEPDriver_AllocateDataPoolMemory(   (DxUint8_t*)contextObject_ptr, 
                                                sizeof(TLK_CERT_1667_ContextObj_t), 
                                                &contObjSMPhy, 
                                                &contObjSMVirt);
    TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

    error = SEPDriver_WriteToDataPoolMemory(    contObjSMVirt, 
                                                (DxUint8_t*)contextObject_ptr, 
                                                sizeof(TLK_CERT_1667_ContextObj_t));
    TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

    error = SEPDriver_AllocateDataPoolMemory(  (DxUint8_t*)cvpoObject_ptr, 
                                                sizeof(TLK_CERT_1667_CPVO_t), 
                                                &cvpoSMPhy, 
                                                &cvpoSMVirt);
    TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

    /************************************************************************/
    /* Start sending message to SeP                                         */
    /************************************************************************/
    SEPDriver_StartMessage(&sramOffset);

    paramInBuffer[0] = TLK_CERT_1667_CHAIN_VALIDATION_TERMINATE_MSG_OP_CODE;
    paramInBuffer[1] = contObjSMPhy;
    paramInBuffer[2] = cvpoSMPhy;


    /* Send constant part */
    error = SEPDriver_WriteParamater(           (DxUint32_t)paramInBuffer,
                                                sizeof(DxUint32_t) * DX_3_WORDS_PARAMS,
                                                sizeof(DxUint32_t) * DX_3_WORDS_PARAMS,
                                                &sramOffset,
                                                DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* End message                                                          */
    /************************************************************************/
    SEPDriver_EndMessage(sramOffset);

    /************************************************************************/
    /* Wait for the response                                                */
    /************************************************************************/
    error = SEPDriver_POLL_FOR_REPONSE();
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* Start reading message from the SEP                                   */
    /************************************************************************/
    /* Start the message */
    error = SEPDriver_StartIncomingMessage(&sramOffset);
    if(error)
    {
        goto end_function_unlock;
    }
    /* Read opcode + status  */
    error = SEPDriver_ReadParamater((DxUint32_t)paramOutBuffer,
                                    sizeof(DxUint32_t) * 2,
                                    sizeof(DxUint32_t) * 2,
                                    &sramOffset ,
                                    DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /* check the opcode */
    if(paramOutBuffer[0] != TLK_CERT_CHAIN_VALIDATION_TERMINATE_MSG_OP_CODE)
    {
        error = DX_WRONG_OPCODE_FROM_SEP_ERR;
        goto end_function_unlock;
    }

    /* check the status */
    if(paramOutBuffer[1] != TLK_CERT_RC_OK)
    {
        error = paramOutBuffer[1];
        goto end_function_unlock;
    }

    /* Get cvpoObject_ptr */
    error = SEPDriver_ReadFromDataPoolMemory(cvpoSMVirt,
                                            (DxUint8_t*)cvpoObject_ptr,
                                            sizeof(TLK_CERT_1667_CPVO_t));

    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

end_function_unlock:   
    /* lock access to the SEP */
    SEPDriver_Unlock();

    return error;
}

