text: /*
   * Amazon FreeRTOS OTA V1.0.3
   * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy of
   * this software and associated documentation files (the "Software"), to deal in
   * the Software without restriction, including without limitation the rights to
   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
   * the Software, and to permit persons to whom the Software is furnished to do so,
   * subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in all
   * copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
   * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
   * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
   * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   *
   * http://aws.amazon.com/freertos
   * http://www.FreeRTOS.org
   */
  
  /* Standard includes. */
  #include <stdint.h>
  #include <stdbool.h>
  #include <string.h>
  #include <stdio.h>
  
  /* FreeRTOS includes. */
  #include "FreeRTOS.h"
  
  #include "unity_fixture.h"
  #include "unity.h"
  #include "aws_ota_pal_test_access_declare.h"
  #include "aws_ota_pal.h"
  #include "aws_ota_agent.h"
  #include "iot_pkcs11.h"
  #include "iot_pkcs11_config.h"
  #include "aws_ota_codesigner_certificate.h"
  #include "aws_test_ota_config.h"
  #include "aws_dev_mode_key_provisioning.h"
  
  /* The Texas Instruments CC3220SF has special requirements on its file system security.
   * We enable code specially for testing the OTA PAL layer for this device. */
  #ifdef CC3220sf
      #include <ti/drivers/net/wifi/simplelink.h>
  #endif
  
  /* For the prvPAL_WriteBlock_WriteManyBlocks test this is the number of blocks of
   * ucDummyData to write to the non-volatile memory. */
  #define testotapalNUM_WRITE_BLOCKS         10
  
  /* For the prvPAL_WriteBlock_WriteManyBlocks test this the delay time in ms following
   * the block write loop. */
  #define testotapalWRITE_BLOCKS_DELAY_MS    5000
  
  /*
   * @brief: This dummy data is prepended by a SHA1 hash generated from the rsa-sha1-signer
   * certificate and keys in tests/common/ota/test_files.
   *
   * The RSA SHA256 signature and ECDSA 256 signature are generated from this entire data
   * block as is.
   */
  static uint8_t ucDummyData[] =
  {
      0x83, 0x0b, 0xf0, 0x6a, 0x81, 0xd6, 0xca, 0xd7, 0x08, 0x22, 0x0d, 0x6a,
      0x33, 0xfa, 0x31, 0x9f, 0xa9, 0x5f, 0xb5, 0x26, 0x00, 0x01, 0x02, 0x03,
      0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f,
      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
      0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
      0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
      0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
  };
  
  /* Global static OTA file context used in every test. This context is reset to all zeros
   * before every test. */
  static OTA_FileContext_t xOtaFile;
  
  #ifdef CC3220sf
  
  /**
   * @brief In the Texas Instruments CC3220(SF) device, we need to restore
   * mcuflashimage.bin to factory following tests that increase the number
   * of security alerts.
   */
      static void prvResetTiCc3220ToFactoryImage()
      {
          int32_t lResult, lRetVal, lExtendedError;
          SlFsRetToFactoryCommand_t xRetToFactoryCommand;
  
          xRetToFactoryCommand.Operation = SL_FS_FACTORY_RET_TO_IMAGE;
          lResult = sl_FsCtl( ( SlFsCtl_e ) SL_FS_CTL_RESTORE, 0, NULL, ( _u8 * ) &xRetToFactoryCommand, sizeof( SlFsRetToFactoryCommand_t ), NULL, 0, NULL );
  
          if( ( _i32 ) lResult < 0 )
          {
              /*Pay attention, for this function the lResult is composed from Signed lRetVal & extended error */
              lRetVal = ( _i16 ) lResult >> 16;
              lExtendedError = ( _u16 ) lResult & 0xFFFF;
              configPRINTF( ( "Error SL_FS_FACTORY_RET_TO_IMAGE, 5d, %d\r\n", lRetVal, lExtendedError ) );
              return;
          }
  
          /* Reset the network processor. */
          sl_Stop( 0 );
          vTaskDelay( pdMS_TO_TICKS( 1000 ) );
          sl_Start( NULL, NULL, NULL );
      }
  #endif /* ifdef CC3220sf */
  
  /**
   * @brief Test group definition.
   */
  TEST_GROUP( Full_OTA_PAL );
  
  TEST_SETUP( Full_OTA_PAL )
  {
      /* Always reset the OTA file context before each test. */
      memset( &xOtaFile, 0, sizeof( xOtaFile ) );
  }
  
  TEST_TEAR_DOWN( Full_OTA_PAL )
  {
      #ifdef CC3220sf
          prvResetTiCc3220ToFactoryImage();
      #else
          OTA_Err_t xOtaStatus;
  
          /* We want to abort the OTA file after every test. This closes the OtaFile. */
          xOtaStatus = prvPAL_Abort( &xOtaFile );
  
          if( kOTA_Err_None != xOtaStatus )
          {
              configPRINTF( ( "Error aborting xOtaFile with code: %d", xOtaStatus ) );
          }
      #endif /* ifdef CC3220sf */
  }
  
  TEST_GROUP_RUNNER( Full_OTA_PAL )
  {
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CloseFile_ValidSignature );
      /* RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CloseFile_NullParameters ); */ /* Not supported yet. */
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CloseFile_InvalidSignatureBlockWritten );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CloseFile_InvalidSignatureNoBlockWritten );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CloseFile_NonexistingCodeSignerCertificate );
  
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CreateFileForRx_CreateAnyFile );
      /* RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CreateFileForRx_NullParameters ) */ /* Not supported yet. */
  
      /* Other failure case testing for prvPAL_CreateFileForRx() is not possible
       * because the MCU's underlying non-volatile memory will have to be mocked
       * to return failures for creating a new file. */
  
      /* RUN_TEST_CASE( Full_OTA_PAL, prvPAL_Abort_NullFileContext ); */ /* Not supported yet. */
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_Abort_OpenFile );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_Abort_FileWithBlockWritten );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_Abort_NullFileHandle );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_Abort_NonExistentFile );
  
      /* RUN_TEST_CASE( Full_OTA_PAL, prvPAL_WriteBlock_NullParameters ); */ /* Not supported yet. */
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_WriteBlock_WriteSingleByte );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_WriteBlock_WriteManyBlocks );
  
      /* This test resets the device so it is not valid for an MCU. */
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_ActivateNewImage );
  
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_SetPlatformImageState_SelfTestImageState );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_SetPlatformImageState_InvalidImageState );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_SetPlatformImageState_UnknownImageState );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_SetPlatformImageState_RejectImageState );
      /* This test is not supported on WinSim because we simply record the image state passed in into a file. */
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_SetPlatformImageState_AcceptedImageStateButImageNotClosed );
  
      /* The successful setting of an image with the accepted state is not supported because that requires
       * an image that was written, verified, and rebooted. */
  
  
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_GetPlatformImageState_InvalidImageStateFromFileCloseFailure );
  
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_ReadAndAssumeCertificate_ExistingFile );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_ReadAndAssumeCertificate_NonexistentFile );
      /* RUN_TEST_CASE( Full_OTA_PAL, prvPAL_ReadAndAssumeCertificate_NullParameters ); */ /* Not supported yet. */
  
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CheckFileSignature_ValidSignature );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CheckFileSignature_InvalidSignatureBlockWritten );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CheckFileSignature_InvalidSignatureNoBlockWritten );
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CheckFileSignature_NonexistingCodeSignerCertificate );
      /* RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CheckFileSignature_NullParameters ); */ /* Not supported yet. */
  
      /* This test must run last.  It provisions the code sign certificate,
       * and other tests exercise the non-flash version.*/
      RUN_TEST_CASE( Full_OTA_PAL, prvPAL_CloseFile_ValidSignatureKeyInFlash );
  }
  
  /**
   * @brief Test prvPAL_CloseFile with a valid signature and signature verification
   * certificate. Verify the success.
   */
  TEST( Full_OTA_PAL, prvPAL_CloseFile_ValidSignature )
  {
      OTA_Err_t xOtaStatus;
      Sig256_t xSig = { 0 };
  
      /* We use a dummy file name here because closing the system designated bootable
       * image with content that is not runnable may cause issues. */
      xOtaFile.pucFilePath = ( uint8_t * ) ( "test_happy_path_image.bin" );
      xOtaFile.ulFileSize = sizeof( ucDummyData );
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      /* We still want to close the file if the test fails somewhere here. */
      if( TEST_PROTECT() )
      {
          /* Write data to the file. */
          xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                          0,
                                          ucDummyData,
                                          sizeof( ucDummyData ) );
          TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
          xOtaFile.pxSignature = &xSig;
          xOtaFile.pxSignature->usSize = ucValidSignatureLength;
          memcpy( xOtaFile.pxSignature->ucData, ucValidSignature, ucValidSignatureLength );
          xOtaFile.pucCertFilepath = ( uint8_t * ) otatestpalCERTIFICATE_FILE;
  
          xOtaStatus = prvPAL_CloseFile( &xOtaFile );
          TEST_ASSERT_EQUAL_INT( kOTA_Err_None, xOtaStatus );
      }
  }
  
  CK_RV prvImportCodeSigningCertificate( const uint8_t * pucCertificate,
                                         size_t xCertificateLength,
                                         uint8_t * pucLabel )
  {
      /* Find the certificate */
      CK_OBJECT_HANDLE xHandle;
      CK_RV xResult;
      CK_FUNCTION_LIST_PTR xFunctionList;
      CK_SLOT_ID xSlotId;
      CK_ULONG xCount = 1;
      CK_SESSION_HANDLE xSession;
      CK_BBOOL xSessionOpen = CK_FALSE;
  
      xResult = C_GetFunctionList( &xFunctionList );
  
      if( CKR_OK == xResult )
      {
          xResult = xInitializePKCS11();
      }
  
      if( ( CKR_OK == xResult ) || ( CKR_CRYPTOKI_ALREADY_INITIALIZED == xResult ) )
      {
          xResult = xFunctionList->C_GetSlotList( CK_TRUE, &xSlotId, &xCount );
      }
  
      if( CKR_OK == xResult )
      {
          xResult = xFunctionList->C_OpenSession( xSlotId, CKF_SERIAL_SESSION, NULL, NULL, &xSession );
      }
  
      if( CKR_OK == xResult )
      {
          xSessionOpen = CK_TRUE;
          xResult = xProvisionCertificate( xSession,
                                           ( uint8_t * ) pucCertificate,
                                           xCertificateLength,
                                           pucLabel,
                                           &xHandle );
      }
  
      if( xSessionOpen == CK_TRUE )
      {
          xResult = xFunctionList->C_CloseSession( xSession );
      }
  
      return xResult;
  }
  
  /**
   * @brief Test prvPAL_CloseFile with a valid signature and signature verification
   * certificate when the code verification key has already been imported to flash.
   * Verify the success.
   */
  TEST( Full_OTA_PAL, prvPAL_CloseFile_ValidSignatureKeyInFlash )
  {
      #if ( otatestpalREAD_CERTIFICATE_FROM_NVM_WITH_PKCS11 == 1 )
          OTA_Err_t xOtaStatus;
          Sig256_t xSig = { 0 };
          CK_RV xResult;
  
          /* Import the code signing certificate into NVM using the PKCS #11 module. */
          xResult = prvImportCodeSigningCertificate( ( const uint8_t * ) signingcredentialSIGNING_CERTIFICATE_PEM,
                                                     sizeof( signingcredentialSIGNING_CERTIFICATE_PEM ),
                                                     ( uint8_t * ) pkcs11configLABEL_CODE_VERIFICATION_KEY );
          TEST_ASSERT_EQUAL( CKR_OK, xResult );
  
          /* We use a dummy file name here because closing the system designated bootable
           * image with content that is not runnable may cause issues. */
          /* xOtaFile.pucFilePath = otatestpalFIRMWARE_FILE; */
          xOtaFile.pucFilePath = ( uint8_t * ) ( "test_happy_path_image.bin" );
          xOtaFile.ulFileSize = sizeof( ucDummyData );
          xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
          TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
          /* We still want to close the file if the test fails somewhere here. */
          if( TEST_PROTECT() )
          {
              /* Write data to the file. */
              xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                              0,
                                              ucDummyData,
                                              sizeof( ucDummyData ) );
              TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
              xOtaFile.pxSignature = &xSig;
              xOtaFile.pxSignature->usSize = ucValidSignatureLength;
              memcpy( xOtaFile.pxSignature->ucData, ucValidSignature, ucValidSignatureLength );
              /* The PKCS #11 label is used to retrieve the code signing certificate. */
              xOtaFile.pucCertFilepath = ( uint8_t * ) pkcs11configLABEL_CODE_VERIFICATION_KEY;
  
              xOtaStatus = prvPAL_CloseFile( &xOtaFile );
              TEST_ASSERT_EQUAL_INT( kOTA_Err_None, xOtaStatus );
          }
      #endif /* if ( otatestpalREAD_CERTIFICATE_FROM_NVM_WITH_PKCS11 == 1 ) */
  }
  
  
  /**
   * @brief Call prvPAL_CloseFile with an invalid signature in the file context.
   * The close is called after we have a written a block of dummy data to the file.
   * Verify the correct OTA Agent level error code is returned from prvPAL_CloseFile.
   */
  TEST( Full_OTA_PAL, prvPAL_CloseFile_InvalidSignatureBlockWritten )
  {
      OTA_Err_t xOtaStatus;
      Sig256_t xSig = { 0 };
  
      /* Create a local file using the PAL. */
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaFile.ulFileSize = sizeof( ucDummyData );
  
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      /* We still want to close the file if the test fails somewhere here. */
      if( TEST_PROTECT() )
      {
          /* Write data to the file. */
          xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                          0,
                                          ucDummyData,
                                          sizeof( ucDummyData ) );
          TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
          /* Fill out an incorrect signature. */
          xOtaFile.pxSignature = &xSig;
          xOtaFile.pxSignature->usSize = ucInvalidSignatureLength;
          memcpy( xOtaFile.pxSignature->ucData, ucInvalidSignature, ucInvalidSignatureLength );
          xOtaFile.pucCertFilepath = ( uint8_t * ) otatestpalCERTIFICATE_FILE;
  
          /* Try to close the file. */
          xOtaStatus = prvPAL_CloseFile( &xOtaFile );
  
          if( ( kOTA_Err_BadSignerCert != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) &&
              ( kOTA_Err_SignatureCheckFailed != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) &&
              ( kOTA_Err_FileClose != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) )
          {
              TEST_ASSERT_TRUE( 0 );
          }
      }
  }
  
  /**
   * @brief Call prvPAL_CloseFile with an invalid signature in the file context.
   * The close is called when no blocks have been written to the file.
   * Verify the correct OTA Agent level error code is returned from prvPAL_CloseFile.
   */
  TEST( Full_OTA_PAL, prvPAL_CloseFile_InvalidSignatureNoBlockWritten )
  {
      OTA_Err_t xOtaStatus;
      Sig256_t xSig = { 0 };
  
      /* Create a local file using the PAL. */
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      /* Fill out an incorrect signature. */
      xOtaFile.pxSignature = &xSig;
      xOtaFile.pxSignature->usSize = ucInvalidSignatureLength;
      memcpy( xOtaFile.pxSignature->ucData, ucInvalidSignature, ucInvalidSignatureLength );
      xOtaFile.pucCertFilepath = ( uint8_t * ) otatestpalCERTIFICATE_FILE;
  
      /* We still want to close the file if the test fails somewhere here. */
      if( TEST_PROTECT() )
      {
          /* Try to close the file. */
          xOtaStatus = prvPAL_CloseFile( &xOtaFile );
  
          if( ( kOTA_Err_BadSignerCert != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) &&
              ( kOTA_Err_SignatureCheckFailed != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) &&
              ( kOTA_Err_FileClose != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) )
          {
              TEST_ASSERT_TRUE( 0 );
          }
      }
  }
  
  /**
   * @brief Call prvPAL_CloseFile with a signature verification certificate path does
   * not exist in the system. Verify the correct OTA Agent level error code is returned
   * from prvPAL_CloseFile.
   *
   * @note This test is only valid if your device uses a file system in your non-volatile memory.
   * Some devices may revert to using aws_codesigner_certificate.h if a file is not found, but
   * that option is not being enforced.
   */
  TEST( Full_OTA_PAL, prvPAL_CloseFile_NonexistingCodeSignerCertificate )
  {
      #if ( otatestpalUSE_FILE_SYSTEM == 1 )
          OTA_Err_t xOtaStatus;
          Sig256_t xSig = { 0 };
  
          memset( &xOtaFile, 0, sizeof( xOtaFile ) );
  
          /* Create a local file using the PAL. */
          xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
          xOtaFile.ulFileSize = sizeof( ucDummyData );
  
          xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
          TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
          /* We still want to close the file if the test fails somewhere here. */
          if( TEST_PROTECT() )
          {
              /* Write data to the file. */
              xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                              0,
                                              ucDummyData,
                                              sizeof( ucDummyData ) );
              TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
              /* Check the signature (not expected to be valid in this case). */
              xOtaFile.pxSignature = &xSig;
              xOtaFile.pxSignature->usSize = ucValidSignatureLength;
              memcpy( xOtaFile.pxSignature->ucData, ucValidSignature, ucValidSignatureLength );
              xOtaFile.pucCertFilepath = ( uint8_t * ) ( "nonexistingfile.crt" );
  
              xOtaStatus = prvPAL_CloseFile( &xOtaFile );
  
              if( ( kOTA_Err_BadSignerCert != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) &&
                  ( kOTA_Err_SignatureCheckFailed != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) &&
                  ( kOTA_Err_FileClose != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) )
              {
                  TEST_ASSERT_TRUE( 0 );
              }
          }
      #endif /* if ( otatestpalUSE_FILE_SYSTEM == 1 ) */
  }
  
  /**
   * @brief Create a file with any name, and verify success.
   */
  TEST( Full_OTA_PAL, prvPAL_CreateFileForRx_CreateAnyFile )
  {
      OTA_Err_t xOtaStatus;
  
      memset( &xOtaFile, 0, sizeof( OTA_FileContext_t ) );
  
      /* TEST: Create a local file using the PAL. Verify error in close. */
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  }
  
  /**
   * @brief Abort on an open file. Verify success.
   */
  TEST( Full_OTA_PAL, prvPAL_Abort_OpenFile )
  {
      OTA_Err_t xOtaStatus;
  
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
  
      /* Create a local file using the PAL. */
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      /* Signal that the download is being aborted. */
      xOtaStatus = prvPAL_Abort( &xOtaFile );
      TEST_ASSERT_EQUAL_INT( kOTA_Err_None, xOtaStatus );
  
      /* Verify that the file handle is null. */
      TEST_ASSERT_EQUAL_INT( NULL, xOtaFile.pucFile );
  }
  
  /**
   * @brief Abort after writing a block to an open file. Verify success.
   */
  TEST( Full_OTA_PAL, prvPAL_Abort_FileWithBlockWritten )
  {
      OTA_Err_t xOtaStatus;
  
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaFile.ulFileSize = sizeof( ucDummyData );
  
      /* Create a local file again using the PAL. */
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      /* We still want to close the file if the test fails here. */
      if( TEST_PROTECT() )
      {
          /* Write data to the file. */
          xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                          0,
                                          ucDummyData,
                                          sizeof( ucDummyData ) );
          TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
      }
  
      /* Signal that the download is being aborted. */
      xOtaStatus = prvPAL_Abort( &xOtaFile );
      TEST_ASSERT_EQUAL_INT( kOTA_Err_None, xOtaStatus );
  
      /* Verify that the file handle is null. */
      TEST_ASSERT_EQUAL_INT( NULL, xOtaFile.pucFile );
  }
  
  /**
   * @brief Call prvPAL_Abort on a NULL file handle. Verify there is no error.
   */
  TEST( Full_OTA_PAL, prvPAL_Abort_NullFileHandle )
  {
      OTA_Err_t xOtaStatus;
  
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
  
      xOtaFile.lFileHandle = 0;
      xOtaStatus = prvPAL_Abort( &xOtaFile );
      TEST_ASSERT_EQUAL_INT( kOTA_Err_None, xOtaStatus );
  }
  
  /**
   * @brief Verify there is no error for aborting a file that doesn't exist.
   */
  TEST( Full_OTA_PAL, prvPAL_Abort_NonExistentFile )
  {
      OTA_Err_t xOtaStatus;
  
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
  
      xOtaFile.pucFilePath = ( uint8_t * ) ( "nonexistingfile.bin" );
      xOtaStatus = prvPAL_Abort( &xOtaFile );
      TEST_ASSERT_EQUAL_INT( kOTA_Err_None, ( xOtaStatus & ~kOTA_PAL_ErrMask ) );
  }
  
  /**
   * Write one byte of data and verify success.
   */
  TEST( Full_OTA_PAL, prvPAL_WriteBlock_WriteSingleByte )
  {
      OTA_Err_t xOtaStatus;
      int16_t sNumBytesWritten;
      uint8_t ucData = 0xAA;
  
      /* TEST: Write a byte of data. */
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      if( TEST_PROTECT() )
      {
          sNumBytesWritten = prvPAL_WriteBlock( &xOtaFile, 0, &ucData, 1 );
          TEST_ASSERT_EQUAL_INT( 1, sNumBytesWritten );
      }
  }
  
  /**
   * @brief Write many blocks of data to a file opened in the device. Verify success.
   */
  TEST( Full_OTA_PAL, prvPAL_WriteBlock_WriteManyBlocks )
  {
      OTA_Err_t xOtaStatus;
      int16_t sNumBytesWritten;
  
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaFile.ulFileSize = sizeof( ucDummyData ) * testotapalNUM_WRITE_BLOCKS;
      /* TEST: Write many bytes of data. */
  
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      if( TEST_PROTECT() )
      {
          int lIndex = 0;
  
          for( lIndex = 0; lIndex < testotapalNUM_WRITE_BLOCKS; lIndex++ )
          {
              sNumBytesWritten = prvPAL_WriteBlock( &xOtaFile, lIndex * sizeof( ucDummyData ), ucDummyData, sizeof( ucDummyData ) );
              TEST_ASSERT_EQUAL_INT( sizeof( ucDummyData ), sNumBytesWritten );
          }
  
          /* Sufficient delay for flash write to complete. */
          vTaskDelay( pdMS_TO_TICKS( testotapalWRITE_BLOCKS_DELAY_MS ) );
      }
  }
  
  /**
   * Call prvPAL_ActivateNewImage() and verify success. This function is expected to
   * reset the device, so this test is only supported on the Windows Simulator environment.
   * The Windows Simulator environment does not reset.
   */
  TEST( Full_OTA_PAL, prvPAL_ActivateNewImage )
  {
      #ifdef WIN32
          OTA_Err_t xOtaStatus = prvPAL_ActivateNewImage();
  
          TEST_ASSERT_EQUAL_INT( kOTA_Err_None, xOtaStatus );
      #endif
  }
  
  /**
   * @brief Set the platform state to self-test and verify success.
   */
  TEST( Full_OTA_PAL, prvPAL_SetPlatformImageState_SelfTestImageState )
  {
      OTA_Err_t xOtaStatus;
  
      OTA_ImageState_t eImageState = eOTA_ImageState_Unknown;
  
      /* Create a local file again using the PAL. */
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaFile.ulFileSize = sizeof( ucDummyData );
  
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      /* We still want to close the file if the test fails. */
      if( TEST_PROTECT() )
      {
          /* Write data to the file. */
          xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                          0,
                                          ucDummyData,
                                          sizeof( ucDummyData ) );
          TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
          /* Set the image state. */
          eImageState = eOTA_ImageState_Testing;
          xOtaStatus = prvPAL_SetPlatformImageState( eImageState );
          TEST_ASSERT_EQUAL_INT( kOTA_Err_None, xOtaStatus );
  
          /* Verify that image state was saved correctly. */
  
          /* [**]All platforms need a reboot of a successfully close image in order to return
           * eOTA_PAL_ImageState_PendingCommit from prvPAL_GetPlatformImageState(). So this cannot be tested.
           */
  
          /*ePalImageState = prvPAL_GetPlatformImageState();
           * TEST_ASSERT_EQUAL_INT( eOTA_PAL_ImageState_PendingCommit, ePalImageState ); */
      }
  }
  
  /**
   * @brief Set an invalid platform image state exceeding the range and verify success.
   */
  TEST( Full_OTA_PAL, prvPAL_SetPlatformImageState_InvalidImageState )
  {
      OTA_Err_t xOtaStatus;
      OTA_ImageState_t eImageState = eOTA_ImageState_Unknown;
  
      /* Create a local file again using the PAL. */
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaFile.ulFileSize = sizeof( ucDummyData );
  
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      /* We still want to close the file if the test fails. */
      if( TEST_PROTECT() )
      {
          /* Write data to the file. */
          xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                          0,
                                          ucDummyData,
                                          sizeof( ucDummyData ) );
          TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
          /* Try to set an invalid image state. */
          eImageState = ( OTA_ImageState_t ) ( eOTA_LastImageState + 1 );
          xOtaStatus = prvPAL_SetPlatformImageState( eImageState );
          TEST_ASSERT_EQUAL( kOTA_Err_BadImageState, ( xOtaStatus & ~kOTA_PAL_ErrMask ) );
      }
  }
  
  /**
   * @brief Set the image state to unknown and verify a failure.
   */
  TEST( Full_OTA_PAL, prvPAL_SetPlatformImageState_UnknownImageState )
  {
      OTA_Err_t xOtaStatus;
      OTA_ImageState_t eImageState = eOTA_ImageState_Unknown;
  
      /* Create a local file again using the PAL. */
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaFile.ulFileSize = sizeof( ucDummyData );
  
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      /* We still want to close the file if the test fails. */
      if( TEST_PROTECT() )
      {
          /* Write data to the file. */
          xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                          0,
                                          ucDummyData,
                                          sizeof( ucDummyData ) );
          TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
          /* Try to set an invalid image state. */
          eImageState = eOTA_ImageState_Unknown;
          xOtaStatus = prvPAL_SetPlatformImageState( eImageState );
          TEST_ASSERT_EQUAL( kOTA_Err_BadImageState, ( xOtaStatus & ~kOTA_PAL_ErrMask ) );
      }
  }
  
  /**
   * @brief Set the image state to accepted with an image that was never closed. We are
   * expecting an error in this case.
   * Verify the correct OTA Agent level error code is returned from prvPAL_SetPlatformImageState.
   */
  TEST( Full_OTA_PAL, prvPAL_SetPlatformImageState_AcceptedImageStateButImageNotClosed )
  {
      #ifndef WIN32
          OTA_Err_t xOtaStatus;
          OTA_ImageState_t eImageState = eOTA_ImageState_Unknown;
  
          /* Create a local file again using the PAL. */
          xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
          xOtaFile.ulFileSize = sizeof( ucDummyData );
  
          xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
          TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
          /* We still want to close the file if the test fails. */
          if( TEST_PROTECT() )
          {
              /* Write data to the file. */
              xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                              0,
                                              ucDummyData,
                                              sizeof( ucDummyData ) );
              TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
              eImageState = eOTA_ImageState_Accepted;
              xOtaStatus = prvPAL_SetPlatformImageState( eImageState );
              TEST_ASSERT_EQUAL_INT( kOTA_Err_CommitFailed, ( xOtaStatus & ~kOTA_PAL_ErrMask ) );
          }
      #endif /* ifndef WIN32 */
  }
  
  /**
   * @brief Set platform image state to rejected and verify success.
   * We cannot test a reject failed without mocking the underlying non volatile memory.
   */
  TEST( Full_OTA_PAL, prvPAL_SetPlatformImageState_RejectImageState )
  {
      OTA_Err_t xOtaStatus;
      OTA_ImageState_t eImageState = eOTA_ImageState_Unknown;
  
      /* Create a local file again using the PAL. */
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaFile.ulFileSize = sizeof( ucDummyData );
  
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      /* We still want to close the file if the test fails. */
      if( TEST_PROTECT() )
      {
          /* Write data to the file. */
          xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                          0,
                                          ucDummyData,
                                          sizeof( ucDummyData ) );
          TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
          eImageState = eOTA_ImageState_Rejected;
          xOtaStatus = prvPAL_SetPlatformImageState( eImageState );
          TEST_ASSERT_EQUAL_INT( kOTA_Err_None, ( xOtaStatus & ~kOTA_PAL_ErrMask ) );
      }
  }
  
  /**
   * @brief Set the platform image state to aborted.
   * We cannot test a abort failed without mocking the underlying non-volatile memory.
   */
  TEST( Full_OTA_PAL, prvPAL_SetPlatformImageState_AbortImageState )
  {
      OTA_Err_t xOtaStatus;
      OTA_ImageState_t eImageState = eOTA_ImageState_Unknown;
  
      /* Create a local file again using the PAL. */
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaFile.ulFileSize = sizeof( ucDummyData );
  
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      /* We still want to close the file if the test fails. */
      if( TEST_PROTECT() )
      {
          /* Write data to the file. */
          xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                          0,
                                          ucDummyData,
                                          sizeof( ucDummyData ) );
          TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
          eImageState = eOTA_ImageState_Aborted;
          xOtaStatus = prvPAL_SetPlatformImageState( eImageState );
          TEST_ASSERT_EQUAL_INT( kOTA_Err_None, ( xOtaStatus & ~kOTA_PAL_ErrMask ) );
      }
  }
  
  /**
   * @brief Verify that the current image received is in the invalid state after a
   * failure to close the file because of a bad signature.
   */
  TEST( Full_OTA_PAL, prvPAL_GetPlatformImageState_InvalidImageStateFromFileCloseFailure )
  {
      OTA_Err_t xOtaStatus;
      Sig256_t xSig = { 0 };
      OTA_PAL_ImageState_t ePalImageState = eOTA_PAL_ImageState_Unknown;
  
      /* TEST: Invalid image returned from prvPAL_GetPlatformImageState(). Using a failure to close. */
      /* Create a local file again using the PAL. */
      xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
      xOtaFile.ulFileSize = sizeof( ucDummyData );
  
      xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
      TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
      /* We still want to close the file if the test fails. */
      if( TEST_PROTECT() )
      {
          /* Write data to the file. */
          xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                          0,
                                          ucDummyData,
                                          sizeof( ucDummyData ) );
          TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
          /* Check the signature. */
          xOtaFile.pxSignature = &xSig;
          xOtaFile.pxSignature->usSize = ucInvalidSignatureLength;
          memcpy( xOtaFile.pxSignature->ucData, ucInvalidSignature, ucInvalidSignatureLength );
          xOtaFile.pucCertFilepath = ( uint8_t * ) otatestpalCERTIFICATE_FILE;
  
          xOtaStatus = prvPAL_CloseFile( &xOtaFile );
  
          if( ( kOTA_Err_BadSignerCert != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) &&
              ( kOTA_Err_SignatureCheckFailed != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) &&
              ( kOTA_Err_FileClose != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) )
          {
              TEST_ASSERT_TRUE( 0 );
          }
  
          /* The file failed to close, so it is invalid or in an unknown state. */
          ePalImageState = prvPAL_GetPlatformImageState();
          TEST_ASSERT( ( eOTA_PAL_ImageState_Invalid == ePalImageState ) || ( eOTA_PAL_ImageState_Unknown == ePalImageState ) );
      }
  }
  
  
  
  /**
   * @brief Call prvPAL_ReadAndAssumeCertificate with an existing certificate file
   * path. Some OTA PAL implementations may use aws_codesigner_certificate.h, in
   * which case this test should still pass.
   */
  TEST( Full_OTA_PAL, prvPAL_ReadAndAssumeCertificate_ExistingFile )
  {
      #if ( otatestpalREAD_AND_ASSUME_CERTIFICATE_SUPPORTED == 1 )
          uint8_t * pucSignerCert = NULL;
          uint8_t * pucCertName = ( uint8_t * ) otatestpalCERTIFICATE_FILE;
          uint32_t ulSignerCertSize = 0;
  
          pucSignerCert = test_prvPAL_ReadAndAssumeCertificate( pucCertName, &ulSignerCertSize );
  
          /* Verify that the signer certificate returned is not NULL. */
          TEST_ASSERT_MESSAGE( pucSignerCert != NULL, "The returned certificate is NULL." );
  
          /* Verify the signer certificate size. The certificates are one of the expected certificates
           * in test/common/ota/test_files. */
          TEST_ASSERT_GREATER_THAN( 0, ulSignerCertSize );
  
          /* Free the certificate file memory. */
          vPortFree( pucSignerCert );
      #endif /* if ( otatestpalREAD_AND_ASSUME_CERTIFICATE_SUPPORTED == 1 ) */
  }
  
  /**
   * @brief Call test_prvPAL_ReadAndAssumeCertificate with a non existing certificate file
   * path. This test is valid only for devices that abstract their non-volatile memory
   * with a file system.
   */
  TEST( Full_OTA_PAL, prvPAL_ReadAndAssumeCertificate_NonexistentFile )
  {
      #if ( ( otatestpalREAD_AND_ASSUME_CERTIFICATE_SUPPORTED == 1 ) && ( otatestpalUSE_FILE_SYSTEM == 1 ) )
          uint8_t * pucSignerCert = NULL;
          uint8_t * pucCertName = ( uint8_t * ) ( "non-existing-file.pem" );
          uint32_t ulSignerCertSize = 0;
  
          pucSignerCert = test_prvPAL_ReadAndAssumeCertificate( pucCertName, &ulSignerCertSize );
  
          /* Verify that the signer certificate returned is NULL. */
          TEST_ASSERT_MESSAGE( pucSignerCert == NULL, "The returned certificate is NULL." );
          /* Verify the signer certificate size is zero. */
          TEST_ASSERT_EQUAL_INT( 0, ulSignerCertSize );
      #endif /* if ( otatestpalREAD_AND_ASSUME_CERTIFICATE_SUPPORTED == 1 ) */
  }
  
  
  /**
   * @brief Call prvPAL_CheckFileSignature with a valid signature on the data block written and
   * expect no errors are returned.
   */
  TEST( Full_OTA_PAL, prvPAL_CheckFileSignature_ValidSignature )
  {
      #if ( otatestpalCHECK_FILE_SIGNATURE_SUPPORTED == 1 )
          OTA_Err_t xOtaStatus;
          Sig256_t xSig = { 0 };
  
          /* Create a local file using the PAL. */
          xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
          xOtaFile.ulFileSize = sizeof( ucDummyData );
  
          xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
          TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
          /* We still want to close the file if the test fails. */
          if( TEST_PROTECT() )
          {
              /* Write data to the file. */
              xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                              0,
                                              ucDummyData,
                                              sizeof( ucDummyData ) );
              TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
              xOtaFile.pxSignature = &xSig;
              xOtaFile.pxSignature->usSize = ucValidSignatureLength;
              memcpy( xOtaFile.pxSignature->ucData, ucValidSignature, ucValidSignatureLength );
              xOtaFile.pucCertFilepath = ( uint8_t * ) otatestpalCERTIFICATE_FILE;
  
              xOtaStatus = test_prvPAL_CheckFileSignature( &xOtaFile );
              TEST_ASSERT_EQUAL_INT( kOTA_Err_None, xOtaStatus );
          }
      #endif /* if ( otatestpalCHECK_FILE_SIGNATURE_SUPPORTED == 1 ) */
  }
  
  /**
   * @brief prvPAL_CheckFileSignature with an invalid signature on the data block
   * written. Verify the signature check fails.
   */
  TEST( Full_OTA_PAL, prvPAL_CheckFileSignature_InvalidSignatureBlockWritten )
  {
      #if ( otatestpalCHECK_FILE_SIGNATURE_SUPPORTED == 1 )
          OTA_Err_t xOtaStatus;
          Sig256_t xSig = { 0 };
  
          /* Create a local file using the PAL. */
          xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
          xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
          TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
          /* We still want to close the file if the test fails. */
          if( TEST_PROTECT() )
          {
              /* Write data to the file. */
              xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                              0,
                                              ucDummyData,
                                              sizeof( ucDummyData ) );
              TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
              /* Fill out an incorrect signature. */
              xOtaFile.pxSignature = &xSig;
              xOtaFile.pxSignature->usSize = ucInvalidSignatureLength;
              memcpy( xOtaFile.pxSignature->ucData, ucInvalidSignature, ucInvalidSignatureLength );
              xOtaFile.pucCertFilepath = ( uint8_t * ) otatestpalCERTIFICATE_FILE;
  
              /* Check the signature. */
              xOtaStatus = test_prvPAL_CheckFileSignature( &xOtaFile );
  
              if( ( kOTA_Err_BadSignerCert != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) &&
                  ( kOTA_Err_SignatureCheckFailed != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) )
              {
                  TEST_ASSERT_TRUE( 0 );
              }
          }
      #endif /* if ( otatestpalCHECK_FILE_SIGNATURE_SUPPORTED == 1 ) */
  }
  
  TEST( Full_OTA_PAL, prvPAL_CheckFileSignature_InvalidSignatureNoBlockWritten )
  {
      #if ( otatestpalCHECK_FILE_SIGNATURE_SUPPORTED == 1 )
          OTA_Err_t xOtaStatus;
          Sig256_t xSig = { 0 };
  
          /* Create a local file using the PAL. */
          xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
          xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
          TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
          /* We still want to close the file if the test fails. */
          if( TEST_PROTECT() )
          {
              /* Fill out an incorrect signature. */
              xOtaFile.pxSignature = &xSig;
              xOtaFile.pxSignature->usSize = ucInvalidSignatureLength;
              memcpy( xOtaFile.pxSignature->ucData, ucInvalidSignature, ucInvalidSignatureLength );
              xOtaFile.pucCertFilepath = ( uint8_t * ) otatestpalCERTIFICATE_FILE;
  
              /* Try to close the file. */
              xOtaStatus = prvPAL_CloseFile( &xOtaFile );
  
              if( ( kOTA_Err_BadSignerCert != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) &&
                  ( kOTA_Err_SignatureCheckFailed != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) )
              {
                  TEST_ASSERT_TRUE( 0 );
              }
          }
      #endif /* if ( otatestpalCHECK_FILE_SIGNATURE_SUPPORTED == 1 ) */
  }
  
  TEST( Full_OTA_PAL, prvPAL_CheckFileSignature_NonexistingCodeSignerCertificate )
  {
      #if ( ( otatestpalCHECK_FILE_SIGNATURE_SUPPORTED == 1 ) && ( otatestpalUSE_FILE_SYSTEM == 1 ) )
          OTA_Err_t xOtaStatus;
          Sig256_t xSig = { 0 };
  
          /* Create a local file using the PAL. */
          xOtaFile.pucFilePath = ( uint8_t * ) otatestpalFIRMWARE_FILE;
          xOtaStatus = prvPAL_CreateFileForRx( &xOtaFile );
          TEST_ASSERT_EQUAL( kOTA_Err_None, xOtaStatus );
  
          /* We still want to close the file if the test fails. */
          if( TEST_PROTECT() )
          {
              /* Write data to the file. */
              xOtaStatus = prvPAL_WriteBlock( &xOtaFile,
                                              0,
                                              ucDummyData,
                                              sizeof( ucDummyData ) );
              TEST_ASSERT_EQUAL( sizeof( ucDummyData ), xOtaStatus );
  
              /* Check the signature (not expected to be valid in this case). */
              xOtaFile.pxSignature = &xSig;
              xOtaFile.pxSignature->usSize = ucValidSignatureLength;
              memcpy( xOtaFile.pxSignature->ucData, ucValidSignature, ucValidSignatureLength );
              xOtaFile.pucCertFilepath = ( uint8_t * ) ( "nonexistingfile.crt" );
  
              xOtaStatus = test_prvPAL_CheckFileSignature( &xOtaFile );
  
              if( ( kOTA_Err_BadSignerCert != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) &&
                  ( kOTA_Err_SignatureCheckFailed != ( xOtaStatus & ~kOTA_PAL_ErrMask ) ) )
              {
                  TEST_ASSERT_TRUE( 0 );
              }
          }
      #endif /* if ( ( otatestpalCHECK_FILE_SIGNATURE_SUPPORTED == 1 ) && ( otatestpalUSE_FILE_SYSTEM == 1 ) ) */
  }
  