Mistake on this page? Email us

Changing a customized porting layer

This section reviews the changes you need to make in each module to migrate it from 1.2 to the current release. Remember that you only need to change customized or proprietary modules.

RTOS module

Description of the main changes

API Changes

The pal_plat_osRandomBuffer API has been changed to add a new output parameter which returns the actual length of the random data.

Root of Trust (RoT)

PAL currently supports the following alternatives for RoT implementation:

  • Hardware RoT: RoT is received from a hardware platform component using a dedicated API: palStatus_t pal_plat_osGetRoTFromHW(uint8_t *keyBuf, size_t keyLenBytes).
  • Generated RoT: RoT is generated on device using the random number generator and securely stored in the Software One Time Programming region (SOTP) (see below).
  • Injected RoT: Customer may store his generated/injected RoT on the SOTP using factory configurator client (FCC).

Warning: Changing the RoT on a device (as part of a software upgrade, for example) will make assets that were previously securely stored on the device inaccessible. If you need access to these assets, extract them before modifying the RoT. This also may apply to the bootloader signing; failure to extract the bootloader signature and make it accessible will render the device unbootable.

PAL_USE_HW_ROT (default value: 1): Defines whether PAL uses a hardware RoT:

  • Set to 1 if the RoT is provided by the platform's hardware. In this case, you must use the function pal_plat_osGetRoTFromHW(uint8_t * key,size_t keyLenBytes) to fetch the RoT from the hardware.

  • Set to 0 if the RoT is software-generated (either by the device's random generator or stored into the SOTP via the FCC). Please refer to the FCC documentation for more details.

    Note: To meet the security requirements when hardware RoT is disabled, you must use the Trusted Internal Storage (see below).

Real Time Clock (RTC)

The PAL_USE_HW_RTC flag defines whether PAL uses hardware RTC, where:

  • 1 (default) is ON.
  • 0 is OFF.

The PAL_USE_HW_RTC flag should only be set to 1 if the device RTC has a backup battery. If PAL_USE_HW_RTC is set to 1, you can enable the RTC startup sequence at the board initialization function. See boardInit.c for more information.

Software One Time Programming (SOTP)

SOTP is now implemented over the flash API (implementing the flash API is mandatory for this release). Ideally, where possible, you should use a hardware RoT, a RTC and hardware TRNG. If your platform does not support this, you can simulate them over flash using the PAL_USE_INTERNAL_FLASH* flag.

  • PAL_USE_INTERNAL_FLASH* (default value: 0): Defines whether there is internal flash on the platform controller, where:

    • 0 (default) means there is no internal flash on the platform controller.
    • 1 means there is internal flash on the platform controller.

    Note: You must set the PAL_USE_INTERNAL_FLASH to 1 to use the following defines.

    • PAL_INTERNAL_FLASH_NUM_#_SECTIONS (default value: 2, max value: 2): The number of sections allocated for security use. Set to 0 if there are no available sections on the internal flash. This should be 2 for all production devices. Having a single section will degrade device lifetime and robustness.
    • PAL_INTERNAL_FLASH_SECTION_#_SIZE: The sector size of each section. Minimum value: 1kB. Set to 0 if there are no available sections on the internal flash.
    • PAL_INTERNAL_FLASH_SECTION_#_ADDRESS: The starting address for each section number (either 1 or 2 depending on how many sections you have defined) for security use. Set to 0 if there are no available section on the internal flash.

    Note: If an individual section's size is larger than a single sector size (as defined in _SIZE), the section must occupy consecutive sectors (as defined in _ADDRESS).

Warning: These storage sections must not be erased, modified or overwritten in any way, including flashing a binary file to the device during manufacturing or upgrading procedures.

Random number Generator

  • PAL_USE_HW_TRNG (default value: 1): Defines whether PAL uses a hardware-based true random number generator (TRNG).

Threading mechanism

The threading mechanism was refactored to simplify the implementation of the porting layer: Previously, each port needed to manage its own logic including thread structures, thread state and thread safety. Now, this logic is handled by the service layer - leaving the port to implement a minimal API. The general idea for the porting layer is to create and run a thread in which the thread wrapper function passes the control of the thread back to the service layer via the palThreadServiceBridge_t structure (see pal_plat_rtos.h for details about this structure). A common thread structure (palThreadData_t) is also provided (see pal_plat_rtos.h for more details about this structure).

What you need to do
  1. Make the following changes to the RoT:

    • If you are using the old HW RoT, set PAL_USE_HW_ROT to 1 and rename the pal_plat_osGetRoT128Bit() function to pal_plat_osGetRoTFromHW().
    • If you are using the new injected/generated RoT, you do not need to make any changes. The old API pal_plat_osGetRoT128Bit is deprecated (no longer required).
  2. If you are using the hardware RTC (PAL_USE_HW_RTC = 1), implement the new RTC APIs:

    • palStatus_t pal_plat_rtcInit(void) - This function initializes the RTC module.
    • palStatus_t pal_plat_rtcDeInit(void) - This function deinitializes the RTC module.
    • palStatus_t pal_plat_osGetRtcTime(uint64_t *rtcGetTime) - This function gets the RTC from the platform.
    • palStatus_t pal_plat_osSetRtcTime(uint64_t rtcSetTime) - This function calls the platform layer and sets the new RTC on the H/W.
  3. Implement the new thread APIs

    • int16_t pal_plat_osThreadTranslatePriority(palThreadPriority_t priority) - translates from palThreadPriority_t to an actual platform-specific thread priority value, that will be stored in the palThreadData_t structure (see pal_plat_rtos.h for details about this structure).

    • palStatus_t pal_plat_osThreadDataInitialize(palThreadPortData* portData, int16_t priority, uint32_t stackSize) - a function which gives the porting layer an opportunity to initialize and store any platform-specific thread information (if any) as part of the thread structure.

      Note: The argument portData is a pointer to a void pointer letting the porting layer store platform-specific information as part of the thread structure for the given thread. If the porting layer does not have any additional information that needs to store as part of the thread, it returns PAL_SUCCESS.

      Note: In conjunction with (the new) API function pal_plat_osThreadRun, this function replaces the legacy API function pal_plat_osThreadCreate.

    • palStatus_t pal_plat_osThreadRun(palThreadServiceBridge_t* bridge, palThreadID_t* osThreadID) - a function which runs the platform specific thread. The bridge argument is the liaison between the porting layer and the service layer. Once the platform calls the created thread function, the porting layer must call bridge->function(bridge->threadData); thus giving control of the thread to the service layer. It is recommended (if possible) that you pass the bridge argument as an argument to the platform-specific thread wrapper function. The bridge argument holds member threadData which is a pointer to the palThreadData_t structure in which all thread information is stored. The porting layer must set argument osThreadID which represents the actual platform-specific thread ID. This value should match the value returned by pal_plat_osThreadGetId.

      Note: In conjunction with (the new) API function pal_plat_osThreadDataInitialize, this function replaces the legacy API function pal_plat_osThreadCreate.

    • palStatus_t pal_plat_osThreadDataCleanup(palThreadData_t* threadData) - a function which gives the porting layer an opportunity to deinitialze any platform-specific thread information (if any) allocated during pal_plat_osThreadDataInitialize.

      Note: This function is called if pal_plat_osThreadTerminate has not been called.

  4. Change existing implementations for the following APIs:

    • palStatus_t pal_plat_osThreadTerminate(palThreadData_t* threadData) - this function's argument has changed from palThreadID_t* threadID to palThreadData_t* threadData.

      Note: If this function is called, the function pal_plat_osThreadDataCleanup will not be called, and it is the porting layer's responsibility to clean up platform-specific thread information (if any) allocated during pal_plat_osThreadDataInitialize.

    • palThreadID_t pal_plat_osThreadGetId(void) - Although the function itself has not changed, the previous implementation returned the PAL thread id and it now returns the actual platform-specific thread ID. The returned value from this function should match the value of the output parameter osThreadID from function pal_plat_osThreadRun.

  5. Remove the following thread APIs:

    • palStatus_t pal_plat_osThreadCreate(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, uint32_t* stackPtr, palThreadLocalStore_t* store, palThreadID_t* threadID) - this function has been split and replaced by functions pal_plat_osThreadDataInitialize and pal_plat_osThreadRun.
    • palThreadLocalStore_t* pal_plat_osThreadGetLocalStore(void) - this function is implemented by the service layer and is no longer needed in the porting layer.

Crypto module

Description of the main changes

  1. A new attribute needs to be extracted from the certificate (certificate ID).
  2. Time certificate verification support.
  3. Add #ifdef over CMAC (Cipher-based Message Authentication Code) functions.

What you need to do

  1. The implementation of the pal_plat_x509CertGetAttribute API has been expanded:
    • pal_plat_x509CertGetAttribute() MUST support the new attribute PAL_X509_CERT_ID_ATTR, the certificate ID is the certificate public key.
  2. Make CMAC functionality support switchable at compile time using the flag PAL_CMAC_SUPPORT by surrounding the CMAC implementation in the porting layer with #ifdef PAL_CMAC_SUPPORT. This reduces the footprint of PAL in cases where CMAC is not required.

TLS module

Description of the main changes

  1. SSL Renegotiation is supported with a new platform API.
  2. Extract server time during handshake from serverHello message.
  3. Time certificate verification support.
  4. Provide time callback function to the TLS/Crypto library - Thread safe.
  5. SSL Get verify function was changed.

What you need to do

  1. Existing platform API was changed (declaration and functionality):
    • palStatus_t pal_plat_handShake(palTLSHandle_t palTLSHandle, uint64_t* serverTime) This API has new output parameter serverTime - which returns the server time sent in the serverHello message in the handshake process.
  2. New platform API was added:
    • palStatus_t pal_plat_renegotiate(palTLSHandle_t palTLSHandle, uint64_t serverTime) This API processes SSL renegotiation and during renegotiation it MUST set the serverTime as the TLS time to be used for certificate verification.
    • Note: Before the function completes, the TLS time MUST return back to the device time.
  3. Time callback for TLS\Crypto library
    • PAL_PRIVATE mbedtls_time_t pal_mbedtlsTimeCB(mbedtls_time_t* timer) This is a thread-safe time function, which returns the device time pal_osGetTime()
    • During renegotiation, the callback MUST use the server time sent during handshake and set in pal_plat_renegotiate().
    • Other threads MUST NOT be affected by this temporary time change.
    • This callback is registered in the palStatus_t pal_plat_initTLSLibrary(void) function.
  4. palStatus_t pal_plat_sslGetVerifyResult(palTLSHandle_t palTLSHandle) returns more informative return values instead of single error PAL_ERR_GENERIC_FAILURE:
    • The list of the new errors (order is important):
    • If certificate validation fails with more than one error, you should order the errors according to the list above.
  5. If you are using mbedtls library as your SSL solution you need to enable the following configuration flags:

For further details, see the Secure Time in TLS porting section.

PAL executables

Description of the main changes

To run on Linux-like operating systems, executables using PAL need the following permissions:


For example, you can set these permissions for the PAL tests by using the following command:

sudo setcap cap_sys_time+epi ./palTests.elf

And then run the tests as follows: