Ejemplo n.º 1
0
VLT_STS CipherUpdate( VLT_PU8 pDataIn, 
        VLT_U32 DataInLen, 
        VLT_U32 dataInCapacity, 
        VLT_PU8 pDataOut, 
        VLT_PU32 pDataOutLen, 
        VLT_U32 dataOutCapacity )
{
    VLT_STS status = VLT_FAIL;
    VLT_U16 blockSize = 0;
    VLT_U32 byteCount = 0;
    VLT_U32 workingLen = 0;
    

    if ( ( ST_UNKNOWN == cipherState ) ||
         ( ST_FINALISED == cipherState ) )
    {
        return( ECPHUPDNOTSUPPORTED );
    }

    /**
     * Cache the block size, we'll use it 
     * frequently.
     */
    blockSize = theCipher.cipherGetBlockSize( );

    /**
     * Ensure we haven't been passed
     * null pointers by the caller.
     */
    if( ( NULL == pDataIn )     ||
        ( NULL == pDataOutLen ) ||
        ( NULL == pDataOut ) )
    {
        return( ECPHUPDNULLPARAM );
    }

    /**
     * For the CipherUpdate the capacity of
     * the buffer passed to us by the caller
     * should be equal or larger than that
     * of the data buffer length.
     */
    if( ( DataInLen > dataInCapacity ) || 
        ( DataInLen > dataOutCapacity ) )
    {
        return( ECPHUPDINVLDCPCT );
    }

    /**
     * Update only deals with data lengths
     * multiple of the block size, if the 
     * client has passed us anything else 
     * other than that then we should exit
     * gracefully-ish!
     */
    if( 0 != ( DataInLen % blockSize ) )
    {
        return( ECPHUPDINVLDLEN );
    }

    /**
     * Chunk things up in multiples of the
     * block size.
     */
    while( 0 != ( DataInLen - byteCount ) )
    {
        /*
         * Perform a copy of the input data into a temp buffer
         * this is needed to ensure the input data is not trashed
         * if CBC mode is selected.
         */
        /*
        * No need to check the return type as pointer has been validated
        */
        (void)host_memcpy( &workingBlock[0], &pDataIn[byteCount], blockSize );
        
        /**
         * Do the chaining
         */
        if( VLT_ENCRYPT_MODE == operationalMode )
        {
            if( BLOCK_MODE_CBC == params.chainMode )
            {
                if( ST_INITIALISED == cipherState )
                {
                    /*
                     * Make a copy of the IV of the first round.
                     */
                    /*
                    * No need to check the return type as pointer has been validated
                    */
                    (void)host_memcpy( chainBlock, &(params.pIV[0]), blockSize );
                    
                    cipherState = ST_UPDATED;
                }

                /*
                * No need to check the return type as pointer has been validated
                */
                (void)host_memxor( &workingBlock[0], chainBlock, blockSize );
            }
        }
        else
        {
            if( BLOCK_MODE_CBC == params.chainMode )
            {
                /*
                * No need to check the return type as pointer has been validated
                */
                (void)host_memcpy( tempBlock, &pDataIn[byteCount], blockSize );
            }
        }

        
        /**
         * Set the working length
         */
        workingLen = blockSize;


        /**
         * Do the Encrypt/Decrypt
         */
        if( VLT_OK == ( status = theCipher.cipherUpdate( 
            //&pData[byteCount], 
            &workingBlock[0], /* workingBlock is used to ensure the pDataIn is preserved */
            &workingLen,
            &pDataOut[byteCount],
            &workingLen) ) )
        {
            /**
             * It should be impossible for the block
             * cipher to return a length not equal to 
             * the blockSize, nevertheless if it does
             * exit with an appropriate error code and 
             * set the chaining block back to the IV 
             * for the next call.
             */
            if( workingLen != blockSize )
            {               
                return( ECPHUPDINVLDBLOCK );
            }                       
            
        }
        else
        {
            return( status );
        }

        /**
         * Do the chaining
         */
        if( VLT_ENCRYPT_MODE == operationalMode )
        {
            if( BLOCK_MODE_CBC == params.chainMode )
            {
                /*
                * No need to check the return type as pointer has been validated
                */
                (void)host_memcpy( chainBlock, &pDataOut[byteCount], blockSize );
            }
        }
        else
        {
            if( BLOCK_MODE_CBC == params.chainMode )
            {
                if( ST_INITIALISED == cipherState )
                {
                    /*
                    * No need to check the return type as pointer has been validated
                    */
                    (void)host_memxor( &pDataOut[byteCount], &(params.pIV[0]), blockSize );
                    cipherState = ST_UPDATED;
                }
                else
                {
                    /*
                    * No need to check the return type as pointer has been validated
                    */
                    (void)host_memxor( &pDataOut[byteCount], chainBlock, blockSize );             
                }

                /*
                * No need to check the return type as pointer has been validated
                */
                (void)host_memcpy( chainBlock, tempBlock, blockSize );
            }
        }
        
        /**
         * Update the byte count to 
         * move to the next block of data.
         */
        byteCount += workingLen;
    }       
    
    *pDataOutLen = byteCount;

    return( VLT_OK );
}