/**@@@+++@@@@******************************************************************
**
** Microsoft Windows Media
** Copyright (C) Microsoft Corporation. All rights reserved.
**
***@@@---@@@@******************************************************************
*/

#ifdef DX_WMDRM_USE_CRYS
#include <drmcommon.h>
#include <drmpkcrypto.h>
#include "pkcrypto.h"
#include "CRYS.h"
#include "DX_VOS_BaseTypes.h"
#include "SEPDriver.h"
#include "error.h"
#include "wmdrm_host_op_code.h" 
#include "DX_VOS_Mem.h"

 /* ------------------------------------------------------------
 **
 * @brief This function executes a reverse bytes copying from one buffer to another buffer.
 *
 *        Overlapping of buffers is not allowed, excluding the case, when destination and source 
 *        buffers are the same. 
 *        Example of a 5 byte buffer:
 *
 *        dst_ptr[4] = src_ptr[0]     
 *        dst_ptr[3] = src_ptr[1]     
 *        dst_ptr[2] = src_ptr[2]     
 *        dst_ptr[1] = src_ptr[3]     
 *        dst_ptr[0] = src_ptr[4]     
 *
 * @param[in] dst_ptr - The pointer to destination buffer.
 * @param[in] src_ptr - The pointer to source buffer. 
 * @param[in] size    - The size in bytes.
 *
 */
 void DRM_PK_ReverseMemcpy( DRM_BYTE *dst_ptr , DRM_BYTE *src_ptr , DRM_UINT size )
 {
	 /* FUNCTION DECLARATIONS */

	 /* loop variable */
	 DRM_UINT i;

	 /* buffers position identifiers */
	 DRM_UINT buff_dst_pos, buff_src_pos;

	 /* FUNCTION LOGIC */

	 /* execute the reverse copy in case of different buffers */
	 if( dst_ptr != src_ptr )
	 {
		 /* initialize the source and the destination position */
		 buff_dst_pos = size - 1;
		 buff_src_pos = 0;

		 for( i = 0 ; i < size ; i++ )
			 dst_ptr[buff_dst_pos--] = src_ptr[buff_src_pos++];
	 }

     /* execute the reverse copy in the same place */
	 else
	 {
		 DRM_BYTE temp, size1;        

		 size1 = (DRM_BYTE)(size / 2);

		 /* initialize the source and the destination position */
		 buff_dst_pos = size1 - 1;
		 buff_src_pos = size - size1;

		 for( i = 0 ; i < size1 ; i++ )
		 {
			 temp = dst_ptr[buff_dst_pos];
			 dst_ptr[buff_dst_pos--] = src_ptr[buff_src_pos];
			 src_ptr[buff_src_pos++] = temp;
		 }
	 }

	 return;  

 }/* END OF DRM_PK_ReverseMemcpy */

/****************************************************************************************/
/****************************************************************************************/
/* The function DRM_PK_ExportPrivKey is implemented to use CRYS_ECPKI_ExportPrivKey. It */
/* is implemented here becsaue the CRYS core function is not part of the CRYS_AI and    */
/* there fore not implemented in the CC5 wrap functions.								*/
/****************************************************************************************/
/****************************************************************************************/


DRM_RESULT DRM_PK_ExportPrivKey(CRYS_ECPKI_UserPrivKey_t  *UserPrivKey_ptr,
								DRM_BYTE		          PrivKeyOut[ __CB_DECL(PK_ENC_PRIVATE_KEY_LEN)]) 
 {
  /* the Error return code identifier */
  CRYSError_t         Error;
  
  /* offset */
  DxUint32_t          sramOffset;
   
  /* read param */
  DxUint32_t          messageParam[2];
  
  /* max length */
  DxUint32_t          maxLength;  

  /*--------------------
      CODE
  ---------------------*/
  
  /* .................. INITIALIZATIONS  ................................. */ 
	   
  Error = CRYS_OK; /* Error initialization */


  /*............. Checking input parameters   ..............................*/

  /* ...... checking the key database handle pointer ....................  */
  if( UserPrivKey_ptr == DX_NULL )
  {
    Error = CRYS_ECPKI_BUILD_KEY_INVALID_USER_PRIV_KEY_PTR_ERROR;
    goto end_function;
  }
         
  /* ...... checking the validity of the extern Private Key pointer ........ */
  if( PrivKeyOut == DX_NULL )
  {
    Error = CRYS_ECPKI_BUILD_KEY_INVALID_PRIV_KEY_IN_PTR_ERROR;
    goto end_function;
  } 
	  
   /* lock access to the SEP */	  
   Error = SEPDriver_Lock();
   
   if(Error != DX_OK)
   {
       goto end_function;
   }  
  /*----------------------------
      start sending message to SEP 
  -----------------------------*/
  sramOffset = 0;
   
  /* start the message */
  SEPDriver_StartMessage(&sramOffset);
  
  /* prepare params */
  messageParam[0] = DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_EXPORT_ECC_PRIV_KEY_OP_CODE;
  
  /* send params */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam ,
                           sizeof(DxUint32_t),
                           sizeof(DxUint32_t),
                           &sramOffset , 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  /* send public key */
  maxLength = ((sizeof(CRYS_ECPKI_UserPrivKey_t) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_WriteParamater((DxUint32_t)UserPrivKey_ptr ,
                            sizeof(CRYS_ECPKI_UserPrivKey_t),
                            maxLength,
                            &sramOffset,
                            DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
  SEPDriver_EndMessage(sramOffset);
            
  /* wait for the response */
  Error = SEPDriver_POLL_FOR_REPONSE();
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  }
  
                                            
  /*-------------------
    start reading message from the SEP 
  ---------------------*/
   
  /* start the message */
  Error = SEPDriver_StartIncomingMessage(&sramOffset);
  if(Error != DX_OK)
  {
  	goto end_function_unlock;
  }
   
  /* read opcode + status  */
  Error = SEPDriver_ReadParamater((DxUint32_t)messageParam ,
                          sizeof(DxUint32_t) * 2,
                          sizeof(DxUint32_t) * 2,
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
   
  /* check the opcode */
  if(messageParam[0] != DX_SEP_HOST_SEP_PROTOCL_HOST_WMDRM_EXPORT_ECC_PRIV_KEY_OP_CODE)
  {
    Error = DX_WRONG_OPCODE_FROM_SEP_ERR;
    goto end_function_unlock;
  }
   
  /* check the status */
  if(messageParam[1] != CRYS_OK)
  {
    Error = messageParam[1];
    goto end_function_unlock;
  }
  
  maxLength = ((sizeof(PRIVKEY) + 3) / sizeof(DxUint32_t)) * sizeof(DxUint32_t);
  Error = SEPDriver_ReadParamater((DxUint32_t)PrivKeyOut ,
                          sizeof(PRIVKEY),
                          maxLength,
                          &sramOffset , 
                          DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
                                           
  /* ...................... end of function ................................ */   

end_function_unlock:   

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

  return Error;

 

 }
#endif // DX_WMDRM_USE_CRYS



