/**@@@+++@@@@******************************************************************
**
** Microsoft Windows Media
** Copyright (C) Microsoft Corporation. All rights reserved.
**
***@@@---@@@@******************************************************************
*/
#include <drmcommon.h>
#include <drmhmac.h>
#ifndef DX_WMDRM_USE_CRYS

DRM_RESULT DRM_API DRM_HMAC_Init(
    IN OUT   HMAC_CONTEXT *pcontextHMAC,
    IN const DRM_BYTE     *pbKey,
    IN       DRM_UINT      cbKey)
{
    DRM_RESULT dr = DRM_E_LOGICERR;
    DRM_UINT   iCount;

    ChkArg( pcontextHMAC != NULL
         && cbKey        != 0 
         && pbKey        != NULL);

    if( cbKey > SHA_BLOCK_SIZE)
    {
        /* Only use the first SHA_BLOCK_SIZE bytes */
        cbKey = SHA_BLOCK_SIZE;
    }

    ZEROMEM( pcontextHMAC, SIZEOF( *pcontextHMAC ) );

    for(iCount = 0; iCount < cbKey; iCount++)
    {
        PUT_BYTE( pcontextHMAC->rgbBuffer, iCount, GET_BYTE( pbKey, iCount ) ^ 0x36 );
    }

    for(; iCount < SHA_BLOCK_SIZE ; iCount++)
    {
        PUT_BYTE( pcontextHMAC->rgbBuffer, iCount, 0 ^ 0x36 );
    }

    DRM_SHA_Init( &( pcontextHMAC->shaContext ) );
    DRM_SHA_Update(pcontextHMAC->rgbBuffer, SHA_BLOCK_SIZE, &( pcontextHMAC->shaContext ) );


    /* Update the internal context buffer so we don't have to hold onto the key. */
    for(iCount = 0; iCount < cbKey; iCount++)
    {
        PUT_BYTE( pcontextHMAC->rgbBuffer, iCount, GET_BYTE( pbKey, iCount ) ^ 0x5C );
    }

    for(; iCount < SHA_BLOCK_SIZE ; iCount++)
    {
        PUT_BYTE( pcontextHMAC->rgbBuffer, iCount, 0 ^ 0x5C );
    }

    dr = DRM_SUCCESS;

ErrorExit:
    return dr;
}

/******************************************************************************/

DRM_RESULT DRM_API DRM_HMAC_Update(
    IN OUT   HMAC_CONTEXT *pcontextHMAC,
    IN const DRM_BYTE     *pbData,
    IN       DRM_UINT      cbData)
{
    DRM_RESULT dr = DRM_E_LOGICERR;

    ChkArg( pcontextHMAC != NULL );
    if( cbData == 0 )
    {
        dr = DRM_SUCCESS;
        goto ErrorExit;
    }

    ChkArg( pbData );

    DRM_SHA_Update(pbData, cbData, &( pcontextHMAC->shaContext ) );
    dr = DRM_SUCCESS;

ErrorExit:
    return dr;

}

/******************************************************************************/

DRM_RESULT DRM_API DRM_HMAC_Finalize(
    IN OUT HMAC_CONTEXT *pcontextHMAC,
       OUT DRM_BYTE     *pbKeyedHash,
    IN     DRM_UINT      cbKeyedHash )
{
    DRM_RESULT dr = DRM_E_LOGICERR;

    ChkArg( pcontextHMAC != NULL
         && pbKeyedHash  != NULL
         && cbKeyedHash  != 0
         && cbKeyedHash  <= SHA_DIGEST_LEN );

    /* Finish the first SHA operation. */
    DRM_SHA_Finalize( &( pcontextHMAC->shaContext ), pcontextHMAC->shaDigest);

    /* Start second SHA operation */
    DRM_SHA_Init( &( pcontextHMAC->shaContext ) );
    DRM_SHA_Update(pcontextHMAC->rgbBuffer, SHA_BLOCK_SIZE, &( pcontextHMAC->shaContext ) );
    DRM_SHA_Update( pcontextHMAC->shaDigest, SHA_DIGEST_LEN, &( pcontextHMAC->shaContext ) );
    DRM_SHA_Finalize( &( pcontextHMAC->shaContext ) , pcontextHMAC->shaDigest);
    MEMCPY(pbKeyedHash, pcontextHMAC->shaDigest, cbKeyedHash);
    ZEROMEM( pcontextHMAC, SIZEOF( HMAC_CONTEXT ) );
    dr = DRM_SUCCESS;

ErrorExit:
    return dr;

}

#else

DRM_RESULT DRM_API DRM_HMAC_Init(
    IN OUT   HMAC_CONTEXT *pcontextHMAC,
    IN const DRM_BYTE     *pbKey,
    IN       DRM_UINT      cbKey)
{
    DRM_RESULT dr = DRM_E_LOGICERR;

    ChkArg( pcontextHMAC != NULL
         && cbKey        != 0 
         && pbKey        != NULL);
	dr = CRYS_HMAC_Init(&pcontextHMAC->HmacCTX,CRYS_HASH_SHA1_mode,(DRM_BYTE*)pbKey,cbKey);
ErrorExit:
    return dr;
}

/******************************************************************************/

DRM_RESULT DRM_API DRM_HMAC_Update(
    IN OUT   HMAC_CONTEXT *pcontextHMAC,
    IN const DRM_BYTE     *pbData,
    IN       DRM_UINT      cbData)
{
    DRM_RESULT dr = DRM_E_LOGICERR;

    ChkArg( pcontextHMAC != NULL );
	dr = CRYS_HMAC_Update(&pcontextHMAC->HmacCTX,(DRM_BYTE*)pbData,cbData);
ErrorExit:
    return dr;

}

/******************************************************************************/

DRM_RESULT DRM_API DRM_HMAC_Finalize(
    IN OUT HMAC_CONTEXT *pcontextHMAC,
       OUT DRM_BYTE     *pbKeyedHash,
    IN     DRM_UINT      cbKeyedHash )
{
    DRM_RESULT dr = DRM_E_LOGICERR;
	CRYS_HASH_Result_t       HmacResultBuff;

    ChkArg( pcontextHMAC != NULL
         && pbKeyedHash  != NULL
         && cbKeyedHash  != 0
         && cbKeyedHash  <= SHA_DIGEST_LEN );

	dr = CRYS_HMAC_Finish(&pcontextHMAC->HmacCTX,HmacResultBuff);
	MEMCPY(pbKeyedHash, HmacResultBuff, cbKeyedHash);
    ZEROMEM( pcontextHMAC, SIZEOF( HMAC_CONTEXT ) );

ErrorExit:
    return dr;

}

#endif
