8 Integration With MPLAB® X IDE

TrustZone® Project Setup Steps

The PSA Crypto library must be integrated into the Secure project of a TrustZone application.

Step 1: Create TrustZone® Project

  1. Create a new project in MPLAB X: File→New Project→Microchip Embedded→New Application Project.
  2. Select PIC32CM5112SG00100.
  3. Use MPLAB Code Configurator (MCC) to configure peripherals into the Secure or Non-Secure projects, as needed. Refer to the MCC guide to generate code for secure/non-secure peripherals. For more information, see TrustZone Applications.
  4. Use MCC for memory partitioning based on your application requirements to allocate Secure , Non-Secure Flash and RAM areas as explained in memory configuration section above. Refer to the MCC for Flash and SRAM Partitioning section.

Step 2: Add Library to Secure Project

  1. Copy the library package built in the Building the PSA Crypto Library From Source Code section to the project directory.
  2. Right-click Secure project and go to Properties.
  3. Navigate to Project→Libraries→Add Library/Object file.
  4. Add the library paths for these libraries: libtfpsacrypto.a, libhsmlite04777-pic32cm.a.

Step 3: Configure Include Paths

  1. In Secure Project Properties→XC32 (Global Options)→xc32-gcc→Preprocessing and messages.
  2. Add the include directories generated in Building the PSA Crypto Library From Source Code: pic32cmsg-psa-crypto-build\hsmlite\include and directories inside pic32cmsg-psa-crypto-build\include.

Step 4: Initialize PSA Crypto Subsystem

In the Secure project main function, add the PSA initialization as shown below. Note that this is only a reference skeleton code structure. Refer to the Demo Application for PSA section for the implementation.

PSA Init
typedef int32_t psa_status_t;
    /* Initialize all modules */ 
    SYS_Initialize ( NULL ); 
    /* Initialize the PSA Crypto subsystem (must be done before NS handoff) */ 
    psa_status_t psa_status = psa_crypto_init(); 
    if (psa_status != PSA_SUCCESS) 
    { 
       /* PSA init failed - Error handler to be implmented here if needed */ 
    } 
   /* Set the non-secure Main stack and call the reset handler*/

Step 5: Create Veneer Functions

Design veneer functions based on your application’s specific cryptographic requirements. Only expose the PSA operations that your Non-Secure application actually needs:
// nonsecure_entry.c(Secure project) 
#include "psa/crypto.h" 
typedef int32_t psa_status_t;
/* Veneer function for RNG if needed by NS Application*/ 

psa_status_t __attribute__((cmse_nonsecure_entry))
secure_Crypto_Rng_Psa(const secure_Crypto_Rng_Psa_args_t *args)
{
    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
    /* Validate that a pointed-to object resides in the Non-Secure memory.
       Validate that a memory region resides entirely in the Non-Secure memory.
    */
    status = psa_generate_random(args->p_output, (size_t)args->outputSize);
    /* Add a handler here in case of failure or return the error as needed */
    return status;
}

/* Veneer function for SHA if needed by the NS Application - This is for reference only and not the full implementation */ 
__attribute__((cmse_nonsecure_entry)) 
psa_status_t nsc_psa_hash_compute(psa_algorithm_t alg, 
                                  const uint8_t *input, size_t input_length, 
                                  uint8_t *hash, size_t hash_size, 
                                  size_t *hash_length) { 
    return psa_hash_compute(alg, input, input_length, hash, hash_size, hash_length); 
} 

// Add additional veneer functions as needed for your application

Step 6: Non-Secure Application

In the Non-Secure project, call the veneer functions:
// main.c (Non-Secure project) 

#include <stdint.h> 
#include <stddef.h> 

//Parameter struct for generating a random number in PSA
 typedef struct
{
    uint8_t  *p_output;
    uint32_t  outputSize;
} secure_Crypto_Rng_Psa_args_t;
// PSA status type 
typedef int32_t psa_status_t; 
typedef uint32_t psa_algorithm_t; 

#define PSA_SUCCESS ((psa_status_t)0) 
#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x02000009) 
#define OUTPUT_SIZE        (12U)
// Veneer function declarations 
extern psa_status_t secure_Crypto_Rng_Psa(const secure_Crypto_Rng_Psa_args_t *args); 
extern psa_status_t nsc_psa_hash_compute(psa_algorithm_t alg, 
                                         const uint8_t *input,  
                                         size_t input_length, 
                                         uint8_t *hash, size_t hash_size, 
                                         size_t *hash_length); 

 
int main(void) { 
    psa_status_t status; 

    // Generate random bytes 
    uint8_t random_data[32]; 
    secure_Crypto_Rng_Psa_args_t args;
    args.p_output   = random_data;
    args.outputSize = OUTPUT_SIZE;

    return (psa_status_t)secure_Crypto_Rng_Psa(&args);
    if (status != PSA_SUCCESS) { 
        // Handle error 
    } 
    
    // Compute SHA-256 hash 
    const uint8_t message[] = "Hello, PSA Crypto!"; 
    uint8_t hash[32]; 
    size_t hash_length; 

    status = nsc_psa_hash_compute(PSA_ALG_SHA_256, 
                                  message, sizeof(message) - 1, 
                                  hash, sizeof(hash), &hash_length); 

    if (status != PSA_SUCCESS) { 
        // Handle error 
    } 

    while(1) { 
        // Application main loop 
    } 
}