/*
* Creation date : Tue Jun 24 14:20:00 2008
* Last modified : %modify_time%
*/
/** @file
* \brief This file contains implementation of 
* test functions for RSA cryptography
* which worked with LibTomCrypt.
*
* \version CE2_RSA_TST_2.c#1:csrc:1
* \author Ihar Yermalayeu
* \remarks Copyright (C) 2007 by Discretix Technologies Ltd.
* All Rights reserved
*/

/************************ Include Files ***********************/

#include "CE2_TST_Base64.h"
#include "memory.h"

/************************ Defines *****************************/

#define TST_MAX_INPUT_DATA_VEC_SIZE_IN_BYTES 1024
#define TST_MAX_DATA_VEC_SIZE_IN_BYTES       (4 * ((TST_MAX_INPUT_DATA_VEC_SIZE_IN_BYTES + 2) / 3)) + 1

/************************ Enums *******************************/
/************************ Typedefs ****************************/
/************************ Global Data *************************/

/* test data definition from RFC-4648 [10] */
TST_Base64_TestDataStruct TST_Base64_Acceptance_TestData[] =
{
    /****************************************/
    /*        RFC-4648 [9] vectors          */
    /****************************************/
    {
        {"Acceptance test - RFC-4648 [9]/Base64/6ByteData "},
            /*TST_input_data*/
        {0x14,0xfb,0x9c,0x03,0xd9,0x7e},
        /*TST_input_dataSizeInBytes*/
        6,
        /*TST_output_data*/
        {'F','P','u','c','A','9','l','+'},
        /*TST_output_dataSizeInBytes*/
        8
    },
    {
        {"Acceptance test - RFC-4648 [9]/Base64/5ByteData "},
            /*TST_input_data*/
        {0x14,0xfb,0x9c,0x03,0xd9},
        /*TST_input_dataSizeInBytes*/
        5,
        /*TST_output_data*/
        {'F','P','u','c','A','9','k','='},
        /*TST_output_dataSizeInBytes*/
        8
    },
    {
        {"Acceptance test - RFC-4648 [9]/Base64/4ByteData "},
            /*TST_input_data*/
        {0x14,0xfb,0x9c,0x03},
        /*TST_input_dataSizeInBytes*/
        4,
        /*TST_output_data*/
        {'F','P','u','c','A','w','=','='},
        /*TST_output_dataSizeInBytes*/
        8
    },

    /****************************************/
    /*        RFC-4648 [10] vectors         */
    /****************************************/
    {
        {"Acceptance test - RFC-4648 [10]/Base64/0ByteData "},
        /*TST_input_data*/
        {0},
        /*TST_input_dataSizeInBytes*/
        0,
        /*TST_output_data*/
        {0},
        /*TST_output_dataSizeInBytes*/
        0
    },
    {
        {"Acceptance test - RFC-4648 [10]/Base64/1ByteData "},
        /*TST_input_data*/
        {'f',0},
        /*TST_input_dataSizeInBytes*/
        1,
        /*TST_output_data*/
        {'Z','g','=','='},
        /*TST_output_dataSizeInBytes*/
        4
    },
    {
        {"Acceptance test - RFC-4648 [10]/Base64/2ByteData "},
        /*TST_input_data*/
        {'f','o',0},
        /*TST_input_dataSizeInBytes*/
        2,
        /*TST_output_data*/
        {'Z','m','8','='},
        /*TST_output_dataSizeInBytes*/
        4
    },
    {
        {"Acceptance test - RFC-4648 [10]/Base64/3ByteData "},
        /*TST_input_data*/
        {'f','o','o',0},
        /*TST_input_dataSizeInBytes*/
        3,
        /*TST_output_data*/
        {'Z','m','9','v'},
        /*TST_output_dataSizeInBytes*/
        4
    },
    {
        {"Acceptance test - RFC-4648 [10]/Base64/4ByteData "},
        /*TST_input_data*/
        {'f','o','o','b',0},
        /*TST_input_dataSizeInBytes*/
        4,
        /*TST_output_data*/
        {'Z','m','9','v','Y','g','=','='},
        /*TST_output_dataSizeInBytes*/
        8
    },
    {
        {"Acceptance test - RFC-4648 [10]/Base64/5ByteData "},
        /*TST_input_data*/
        {'f','o','o','b','a',0},
        /*TST_input_dataSizeInBytes*/
        5,
        /*TST_output_data*/
        {'Z','m','9','v','Y','m','E','='},
        /*TST_output_dataSizeInBytes*/
        8
    },
    {
        {"Acceptance test - RFC-4648 [10]/Base64/6ByteData "},
        /*TST_input_data*/
        {'f','o','o','b','a','r',0},
        /*TST_input_dataSizeInBytes*/
        6,
        /*TST_output_data*/
        {'Z','m','9','v','Y','m','F','y'},
        /*TST_output_dataSizeInBytes*/
        8
    }
}; /* End of TST_Base64_Acceptance_TestData */

DxUint32_t TST_Base64_Acceptance_TestDataCount = sizeof(TST_Base64_Acceptance_TestData) / sizeof(TST_Base64_Acceptance_TestData[0]);

/************************ Private Functions *******************/
/************************ Public Functions ********************/

/***************************************************************
* Function Name: 
*  CE2_TST_Base64
*
* Inputs:
*  @param out [in] - pointer to file to output debug information;
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  Test for CE2_Base64 methods.
***************************************************************/
CE2Error_t CE2_TST_Base64(FILE *out)
{
    CE2Error_t test_result = CE2_TST_VALID;
    CE2Error_t error       = CE2_OK;
    DxUint8_t  inputBuffer[TST_MAX_INPUT_DATA_VEC_SIZE_IN_BYTES];
    DxUint32_t inputBufferSizeInBytes;
    DxUint8_t  outputBuffer[TST_MAX_DATA_VEC_SIZE_IN_BYTES];
    DxUint32_t outputBufferSizeInBytes;
    DxUint8_t  decodedBuffer[TST_MAX_DATA_VEC_SIZE_IN_BYTES];
    DxUint32_t decodedBufferSizeInBytes;

    PrintTestBeginMsg(out, __FUNCTION__);

    for (inputBufferSizeInBytes = 0;
         inputBufferSizeInBytes < TST_MAX_INPUT_DATA_VEC_SIZE_IN_BYTES;
         ++inputBufferSizeInBytes)
    {
        inputBuffer[inputBufferSizeInBytes] = (DxUint8_t)inputBufferSizeInBytes;
    }

    for (inputBufferSizeInBytes = 2;
         inputBufferSizeInBytes <= TST_MAX_INPUT_DATA_VEC_SIZE_IN_BYTES;
         inputBufferSizeInBytes <<= 1)
    {
        outputBufferSizeInBytes = TST_MAX_DATA_VEC_SIZE_IN_BYTES;

        error = CE2_Base64_Encode(inputBuffer,
                                  inputBufferSizeInBytes,
                                  outputBuffer,
                                  &outputBufferSizeInBytes);

        if (error != CE2_OK)
        {
            fprintf(out, "Can't make Base64 encoding!\n");
            test_result = error;
            break;
        }

        decodedBufferSizeInBytes = TST_MAX_DATA_VEC_SIZE_IN_BYTES;

        error = CE2_Base64_Decode(outputBuffer,
                                  outputBufferSizeInBytes,
                                  decodedBuffer,
                                  &decodedBufferSizeInBytes);

        if (error != CE2_OK)
        {
            fprintf(out, "Can't make Base64 decoding!\n");
            test_result = error;
            break;
        }

        if (inputBufferSizeInBytes != decodedBufferSizeInBytes)
        {
            fprintf(out, "Decoded and source buffer sizes differs!\n");
            test_result = error;
            break;
        }

        error = memcmp(inputBuffer, decodedBuffer, inputBufferSizeInBytes);

        if (error != 0)
        {
            fprintf(out, "Decoded and source buffers data differs!\n");
            test_result = error;
            break;
        }
    }

    PrintTestEndMsg(out, __FUNCTION__, test_result);

    return test_result;
} /* End of CE2_TST_Base64 */

/***************************************************************
* Function Name: 
*  CE2_TST_Base64_Acceptance
*
* Inputs:
*  @param out [in] - pointer to file to output debug information;
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  Acceptance Test for CE2_Base64 methods.
***************************************************************/
CE2Error_t CE2_TST_Base64_Acceptance(FILE *out)
{
    CE2Error_t test_result = CE2_TST_VALID;
    CE2Error_t error       = CE2_OK;
    DxUint32_t i;
    DxUint8_t  outputBuffer[TST_BASE64_MAX_DATA_VEC_SIZE_IN_BYTES];
    DxUint32_t outputBufferSizeInBytes;

    PrintTestBeginMsg(out, __FUNCTION__);

    for (i = 0; i < TST_Base64_Acceptance_TestDataCount; ++i)
    {
        outputBufferSizeInBytes = TST_BASE64_MAX_DATA_VEC_SIZE_IN_BYTES;

        error = CE2_Base64_Encode(TST_Base64_Acceptance_TestData[i].TST_input_data,
                                  TST_Base64_Acceptance_TestData[i].TST_input_dataSizeInBytes,
                                  outputBuffer,
                                  &outputBufferSizeInBytes);

        if (error != CE2_OK)
        {
            fprintf(out, "%s\nCan't make Base64 encoding!\n", TST_Base64_Acceptance_TestData[i].TST_Name);
            test_result = error;
            break;
        }

        if (TST_Base64_Acceptance_TestData[i].TST_output_dataSizeInBytes != outputBufferSizeInBytes)
        {
            fprintf(out, "%s\nEncoded and expected buffer sizes differs!\n", TST_Base64_Acceptance_TestData[i].TST_Name);
            test_result = error;
            break;
        }

        error = memcmp(TST_Base64_Acceptance_TestData[i].TST_output_data, outputBuffer, outputBufferSizeInBytes);

        if (error != 0)
        {
            fprintf(out, "%s\nEncoded and expected buffers data differs!\n", TST_Base64_Acceptance_TestData[i].TST_Name);
            test_result = error;
            break;
        }

        outputBufferSizeInBytes = TST_BASE64_MAX_DATA_VEC_SIZE_IN_BYTES;

        error = CE2_Base64_Decode(TST_Base64_Acceptance_TestData[i].TST_output_data,
                                  TST_Base64_Acceptance_TestData[i].TST_output_dataSizeInBytes,
                                  outputBuffer,
                                  &outputBufferSizeInBytes);

        if (error != CE2_OK)
        {
            fprintf(out, "%s\nCan't make Base64 decoding!\n", TST_Base64_Acceptance_TestData[i].TST_Name);
            test_result = error;
            break;
        }

        if (TST_Base64_Acceptance_TestData[i].TST_input_dataSizeInBytes != outputBufferSizeInBytes)
        {
            fprintf(out, "%s\nDecoded and input buffer sizes differs!\n", TST_Base64_Acceptance_TestData[i].TST_Name);
            test_result = error;
            break;
        }

        error = memcmp(TST_Base64_Acceptance_TestData[i].TST_input_data, outputBuffer, outputBufferSizeInBytes);

        if (error != 0)
        {
            fprintf(out, "%s\nDecoded and source buffers data differs!\n", TST_Base64_Acceptance_TestData[i].TST_Name);
            test_result = error;
            break;
        }
    }

    PrintTestEndMsg(out, __FUNCTION__, test_result);

    return test_result;
} /* End of CE2_TST_Base64_Acceptance */
