Build CodeSafe 5 SDK apps

General SDK use

The CodeSafe 5 SDK provides the tools necessary to build and run SEE machines on nShield 5 HSMs. The CodeSafe 5 SEE machines are containerized. The SDK provides the structure of the container, including a root file system, libraries required for communication with the nCore API, and libraries to enable communication between the SEE machine and the host. The SDK provides libraries for development, libraries built for maintaining backwards compatibility for legacy applications, a root file system with libraries useful for development of new applications, such as libglib and libc, and useful binaries including touch, cat, grep.

Prerequisites

GCC 8.x or later.

SDK file structure overview

SDK location

The default installation location of the CodeSafe 5 SDK is:

  • Linux: /opt/nfast/c/csd5/

  • Windows: C:\Program Files\nCipher\nfast\c\csd5\

Some tools required for SEE machine operations might be found elsewhere in the main install. For example, csadmin, which enables loading, starting, and stopping SEE machines, is installed in the following default locations:

  • Linux: /opt/nfast/bin/csadmin

  • Windows: C:\Program Files\nCipher\nfast\bin\csadmin (Windows)

These cases are described in the following sections as required.

Container root file system

The container root file system is located in:

  • Linux: /opt/nfast/c/csd5/rootfs/

  • Windows: C:\Program Files\nCipher\nfast\c\csd5\rootfs\

This root file system contains two main parts: binary files and libraries.

Binaries

rootfs/bin/ (Linux) or rootfs\bin\ (Windows) contains many useful common Linux binaries that you might need within the container such as cat, grep, and touch.

rootfs/sbin/ (Linux) or rootfs\sbin\ (Windows) contains the init script for the container.

Libraries

rootfs/lib/ and rootfs/usr/lib/ (Linux) or rootfs\lib\ and rootfs\usr\lib\ (Windows) contain various useful libraries a developer might need, such as libglib and libc. Some of these libraries are also essential for the proper running of the container and execution of various examples.

CMake

The SDK installs a directory which includes CMake toolchains used for building example SEE machines:

  • Linux: /opt/nfast/c/csd5/cmake

  • Windows: C:\Program Files\nCipher\nfast\c\csd5\cmake

These toolchains can serve as examples themselves for creating custom toolchains.

Include directories

The SDK provides two directories with header files that can be included along with their respective libraries to provide additional functionality in SEE machines. These headers are stored in:

  • Linux:

    • /opt/nfast/c/csd5/gcc/*

    • /opt/nfast/c/csd5/include-see/*

  • Windows:

    • C:\Program Files\nCipher\nfast\c\csd5\gcc\*

    • C:\Program Files\nCipher\nfast\c\csd5\include-see\*

SEE specific libraries

The C libraries which are specific to SEE machines, including seelib.a and librtusr.a, are located in:

  • Linux: /opt/nfast/c/csd5/lib-ppc64-linux-musl/\*

  • Windows: C:\Program Files\nCipher\nfast\c\csd5\lib-ppc64-linux-musl\*

These libraries must be included to enable critical SEE machine functionality such as communication with the nCore API.

The Python module specific to SEE machines is seeapi.py. This module is located under Python site packages in nshield.ipcdaemon.seeapi. This must be imported as SEEAPI to enable critical SEE machine functionality such as communication with the nCore API.

Legacy compatibility

The CodeSafe 5 SDK and nShield 5 HSMs are sufficiently different from previous implementations that legacy applications cannot run with the CodeSafe 5 SDK. For ease of use, the CodeSafe 5 SDK supplies a compatibility layer in the form of headers, files, and libraries to enable legacy applications to be used in nShield 5 HSMs.

Legacy applications require recompilation with new libraries to run on nShield 5 HSMs. The module-side compatibility library liblegacy_compatibility.a is in the SDK under:

  • Linux: lib-ppc64-linux-musl/

  • Windows: lib-ppc64-linux-musl\

Host-side compatibility files and headers are in the SDK under:

  • Linux: include-see/legacy-compatibility-host/\*

  • Windows: include-see\legacy-compatibility-host\*

This compatibility layer is described here.

Do not use these compatibility layer libraries, files, and headers to create new SEE machines. They are only supplied to allow legacy applications to be quickly re-compiled and run on nShield 5 HSMs.

Building new SEE machines with SEElib

An SEE machine is a container image with a complete filesystem which can be loaded onto an CodeSafe 5-enabled HSM as part of a container. The SEElib library enables SEE machines to interface with the nCore API via the IPC daemon.

Source code is compiled using one of the GCC cross-compilers supplied with the CodeSafe SDK. For details of required compiler options, toolchains, makefiles and so on, see the CMake files supplied with the examples, as well as Build and sign example SEE machines on Linux and Build and sign example SEE machines on Windows.

The container image must be signed using the csadmin utility tool.

Developer authentication

CodeSafe 5 requires a signed CodeSafe image to run SEE machines on the HSM.

The CodeSafe developer needs to request a developer ID certificate by sending a Certificate Signing Request (CSR) to Entrust support. The tool used to create the CSR is integrated into the HSM software as a subcommand of csadmin utility.

For security purposes, a developer keypair must be created and stored within the HSM. In addition, the keypair must be OCS protected to provide authorization control on its use. The developer keypair will be created by csadmin if it does not already exist.

After the certificates are received, they are installed on the HSM and are used to sign CodeSafe application images with the csadmin tool.

The implementation of this is described in more detail in Sign and deploy CodeSafe 5 SDK apps using csadmin.

Deploying SEE machines

After the code has been compiled, built, and signed, the csadmin utility tool is used to deploy the SEE machine. It is used to load the signed CodeSafe application image and then to start the SEE machine. The SEE machine then runs the entrypoint including the main() function.

For more information on the csadmin utility, see Sign and deploy CodeSafe 5 SDK apps using csadmin.

SEE machine initialization requirements

An SEE machine must initialize the SEElib before making use of any of the SEElib functionality. This is done by calling SEElib_init(). It is recommended that this call is made immediately within the main() function of an SEE machine.

SEElib Functions

After initialization, SEElib functions can be used to communicate with the nCore API via the IPC daemon. These methods call functions identically to previous CodeSafe versions although the underlying methodology has changed.

SEElib_Transact()

To send a command to the nCore API and block waiting for a reply:

int SEElib_Transact(struct M_Command *cmd, struct M_Reply *reply)

This sends the cmd command to the nCore API and waits for the reply to be written to reply.

SEElib_Submit() / SEElib_Query()

To send a non-blocking command to the nCore API:

int SEElib_Submit(M_Command *cmd, M_Reply *reply, PEVENT ev, SEElib_ContextHandle tctx)

The cmd command is submitted to the nCore API. The transaction listener thread will call EventSet ev, if ev is non-NULL when the reply returns for this command. The reply is unmarshalled into reply and tctx is returned to the caller with SEElib_Query(M_Reply **replyp, SEElib_ContextHandle *tctx_r).

Before using the SEElib_Submit() method, SEElib_StartTransactListener() must have been called to start the transaction listener.

Unlike SEElib_SubmitCoreJob(), SEElib_Submit() does not block and wait for all other calls to SEElib_Transact() to complete.

SEElib_SubmitCoreJob / SEElib_GetCoreJobEx()

To submit a job to the nCore API:

extern int SEElib_SubmitCoreJob(const unsigned char *data, unsigned int len)

To receive a job from the nCore API:

extern int SEElib_GetCoreJobEx(unsigned char *buf, M_Word *len_io, unsigned flags)

SEElib_SubmitCoreJob() is blocking. It waits for the job to be submitted, which includes waiting for existing calls made to SEElib_Transact() to be completed. The same is true for SEElib_GetCoreJobEx().

For non-blocking calls, consider using SEElib_Submit().

Other SEElib methods

For a comprehensive list of all functionality provided via the SEElib, see: SEE API documentation.

Host/SEE machine communication

The newest CodeSafe 5 implementation simplifies the host/SEE machine connection. Host/SEE machine communication does not need to use SEEJobs or pass through the hardserver and nCore API. Communication between the host-side app and SEE machine is done via TCP/IPv6 networking.

The ncoreapi service can only connect to one CodeSafe container at a time.

Update Connects running in an IPv4 context

The host side of the CodeSafe 5 examples will only be able to communicate over IPv6. Connects running in an IPv4 context will not be able to run examples without changing how CodeSafe 5 is configured on the Connect. To set things up on a Connect, see section CodeSafe setup for the nShield 5c in the nShield 5c User Guide.

The compatibility layer and legacy SEE machines

The CodeSafe 5 SDK provides libraries for developing new SEE machines. It also provides libraries, files, and headers designed for maintaining backwards compatibility with legacy CodeSafe SEE machines.

This section describes changes between previous implementations of the CodeSafe SDK and the CodeSafe 5 SDK. Compatibility layer documentation is only relevant for developers who need to update legacy applications to use the CodeSafe 5. Do not use it as a guide for building new SEE machines.

Major changes

The requirement for a compatibility layer arises from changes made to the overall structure of how CodeSafe 5 SEE machines interact with both the host and with the nCore API.

Host-SEE machine communication

In legacy CodeSafe implementations, for older HSMs, communication between a host-side application and an SEE machine would be done via the nCore API using SEEJobs. Using the nCore API to relay SEEJobs between the host-side and the SEE machine is no longer supported.

Communication via the nCore API has been replaced with direct communication between the host and SEE machine using TCP/UDP socket connections. Optionally, communication can be over an SSH tunnel for security. This allows greater control of the creation, management, and use of connections between the host and SEE machine for developers. It also improves performance as SEEJobs no longer have to be sent to the nCore API before being forwarded to the SEE machine.

SEE machine - nCore API communication

Communication between the host and SEE machine no longer requires the nCore API as an intermediary. Communication intended to be exclusively between the SEE machine and the nCore API has also changed with the addition of the container IPC daemon. The IPC daemon is provided by Entrust, exists within the container, and maintains connections between the container and the nCore API.

The IPC daemon forwards commands to the nCore API sent using the SEElib. Outside of the addition of the intermediary forwarder, the communication between the SEE machine and the nCore API remains functionally unchanged.

The ncoreapi service can only connect to one CodeSafe container at a time.

Compatibility layer use

The compatibility layer contains two main parts: * liblegacy_compatibility.a, the module-side library. * include-see/legacy-compatibility-host/*, the host-side compatibility interface.

Module-side compatibility layer

The module-side compatibility layer provides the methods necessary to connect the SEE machine to the host-side application via network connection.

The module-side compatibility layer comprises the liblegacy_compatibility.a library. Its install location is:

  • Linux: /opt/nfast/c/csd5/lib-ppc64-linux-musl/

  • Windows: C:\Program Files\nCipher\nfast\c\csd5\lib-ppc64-linux-musl\

Legacy SEE machines must be built with liblegacy_compatibility.a. When initialized, the module-side compatibility layer opens and maintains a connection between the host-side application and the SEE machine. This allows legacy applications to continue using SEElib_AwaitJob() and SEElib_ReturnJob() to accept incoming jobs and return them to the host-side application when completed.

Host-side compatibility layer

The host-side compatibility layer provides the methods necessary to connect the host-side application to the SEE machine via network connection.

The host-side compatibility layer comprises the following files:

  • legacy-csee-host-side-compatibility.h contains all necessary function declarations.

  • legacy-csee-host-side-compatibility.c contains required host-side function definitions required to connect to and maintain the connection to legacy SEE machines.

Their install location is:

  • Linux: /opt/nfast/c/csd5/examples/csee/utils/hostside/

  • Windows: C:\Program Files\nCipher\nfast\c\csd5\examples\csee\utils\hostside\

Legacy host-side applications must be built with legacy-csee-host-side-compatibility.h and legacy-csee-host-side-compatibility.c. This is done by emulating the connection which was previously created and managed by the hardserver and the nCore API.

legacy-csee-host-side-compatibility.c is compiled and added to the libutil.a library. Applications should link to it if they need to connect to legacy SEE machines.

Initialize module-side compatibility

Initialize the module-side compatibility layer:

extern void SEElib_Legacy_Support_Init(const char* PORT)

See Classic SEE (CSEE) examples in Port existing CodeSafe application to CodeSafe 5 for how the module-side legacy support can be initialized to open a socket connection at port PORT to communicate between host-side and SEE machines.

Use module-side compatibility

Legacy applications expect incoming messages from the host to be piped from the host to the nCore API via the hardserver. From there, they eventually become accessible within the SEE machine via calls to SEElib_AwaitJob() and SEElib_ReturnJob(). After the module-side compatibility layer is initialized (see Initialize module-side compatibility), these functions will work exactly as they have in previous CodeSafe applications. No further changes are necessary.

Initializing the compatibility layer functionality via the SEElib_Legacy_Support_Init() call allows the compatibility layer to handle incoming and outgoing jobs as would previously have been done by the nCore API. The Classic SEE (CSEE) examples show that the only change made to the SEE machines to allow for backwards compatibility is the initialization of the compatibility layer.

The compatibility layer only supports one client connection at a time while the hardserver can support many.

Initialize host-side application compatibility

Initialize the host-side legacy application to allow connection to the SEE machine, communicating to the host via PORT:

netsee_initialize_legacy_seejob_support(const char * cseeContainerMachineIPv6, const char * cseeContainerMachinePort)`

Here, cseeContainerMachinePort must match the PORT initialized by the SEE machine. cseeContainerMachineIPv6 is the container’s IPv6 address. See the execution of CSEE examples in Port existing CodeSafe application to CodeSafe 5 for more information on passing in the IPv6 address of the container.

netsee_initialize_legacy_seejob_support() establishes a connection to the SEE machine’s container at port cseeContainerMachinePort. The compatibility layer maintains this connection and handles the sending of SEEJobs between the host and module SEE machine.

Use host-side application compatibility

The compatibility layer allows host-side application calls to interact with the SEE machine to remain largely unchanged. Some changes to calls are, however, required. These changes, rather than changing how the functions operate, largely serve to remove no longer required elements, such as NFastApp_Connection.

  • netsee_transact_legacy_seejob(const M_Command *command, M_Reply *reply, struct NFast_Transaction_Context *tctx)

    replaces:

    NFastApp_Transact(NFastApp_Connection conn, struct NFast_Call_Context *cctx, const M_Command *command, M_Reply *reply, struct NFast_Transaction_Context *tctx)

    The NFastApp_Connection and NFast_Call_Context are no longer required and should not be passed in.
  • netsee_simple_transact_legacy_seejob(const M_Command *cmd, M_Reply *reply, int fatal)

    replaces:

    simple_transact (NFastApp_Connection nc, M_Command *pcmd, M_Reply *preply, int fatal)

    The NFastApp_Connection is no longer required and should not be passed in.
  • netsee_submit_legacy_seejob(const M_Command *cmd, M_Reply *reply, struct NFast_Transaction_Context *tctx)

    replaces:

    NFastApp_Submit(NFastApp_Connection conn, struct NFast_Call_Context *cctx, const M_Command *command, M_Reply *reply, struct NFast_Transaction_Context *tctx)

    The NFastApp_Connection and NFast_Call_Context are no longer required and should not be passed in.
  • netsee_wait_legacy_seejob(M_Reply **replyp, struct NFast_Transaction_Context **tctx)

    replaces:

    NFastApp_Wait(NFastApp_Connection conn, struct NFast_Call_Context *cctx, M_Reply **replyp, struct NFast_Transaction_Context **tctx_r)

    The NFastApp_Connection and NFast_Call_Context are no longer required and should not be passed in.

With these changes implemented, legacy host-side applications, when run in conjunction with an SEE machine properly initialized with liblegacy_compatibility.a, should function identically to when run in previous implementations of CodeSafe.

This section demonstrated how to use the compatibility layer to quickly bring legacy applications into the new CodeSafe 5 environment. New applications should never be written with the compatibility layer. It is advised that, when possible, a user defined TCP/IPv6 network connection between the host-side application and the SEE machine is implemented, rather than using the compatibility layer to transact jobs. However, the compatibility layer does perform this job when no such custom implementation can be made.