FM Development
The following chapter describes the recommended development cycle to be undertaken when developing custom functionality modules. The recommended development lifecycle contains the following stages:
NOTE File paths in the examples in this chapter are Linux specific, as development of FMs is done on Linux, only, for this release. Development of host-side FM applications (that call an FM on your HSM) can be done on Windows, as well as Linux.
TERMINOLOGY NOTE - "Token" is the Cryptoki term for what is in a crypto slot. "Partition" is the Luna term for a Cryptoki token. The Admin Token is the HSM Admin or SO partition and exists while the HSM is in initialized state, distinct from user/application partitions that you can create and delete and reinitialize at will.
NOTE For Luna Network HSM 7s, the Luna HSM Client accesses application partitions via NTLS or STC connection, causing the registered application partitions to appear as slots in the LunaCM slot list, just as if they were slots on Luna PCIe HSM 7 cards installed locally in the Luna HSM Client host computer.
>For local Luna PCIe HSM 7s, the HSM Admin (SO) partition (a.k.a. the HSM Admin "Token" in deference to Cryptoki terminology) also appears in the slot list and is directly accessible.
>Be aware that for Luna Network HSM 7s the HSM Admin partition (HSM Admin token) must be accessed over SSH via the appliance's LunaSH administrative interface, and is not visible or accessible via the Client.
Lifecycle Overview
The following diagram illustrates the recommended development cycle to be undertaken when developing functionality modules.
Figure 1: Figure 1 – FM Development Lifecycle
The development process consists of the following stages:
Initial Development:
Includes the design and development of the functionality application code for initial testing.
Adapter Build:
The functionality module should now be built for the HSM environment. The FM is loaded onto the HSM hardware and again tested to ensure that operation is as expected.
Production Build:
The final process during the development lifecycle will be to produce and release the functionality module for the operational environment it was intended.
Initial Development
This phase is the start of the development phase from the specification of the requirements to the completion of the design. Programming the FM, and the host side libraries and or application can also be considered part of this stage. It is assumed that at this stage the test procedures are also developed.
Adapter Build
The FM must be tested in the HSM.
In this phase, the developer generates the binary FM image in DEBUG mode, and signs it using either a temporary or a permanent development key. Once the image is signed, it can be loaded to the HSM for the next stage of testing. Refer to the FM Architecture for further details.
Adapter Test
In the HSM test stage, the debug build of the FM is tested in its production environment.
NOTE If problems are detected during this stage, the developer should use trace messages from the FM to resolve the problem.
Production Build
When the implementation of the FM and the host-side code is correct, a production build of the system is performed. Refer to the FM Architecture for further details.
In this stage, the developer generates the FM binary image, and the responsible person signs it using the production private key.
Acceptance Test
When the production binaries are available, the acceptance tests are performed on the final system before the binaries are released.
Key Management
All FM images loaded into the HSM must have an assigned signature. FMs are executed inside the HSM only after this signature has been validated. The management of the keys used to sign/verify the firmware is completely controlled by the developers of the FM. Thales does not have any responsibility for the FM key management scheme.
The certificate that is used to validate the FM binary image must exist in the Admin Token the Cryptoki term for what is in a slot; in Luna HSMs, a partition of the HSM on which the FM is to be installed. If the certificate does not already exist in the Admin Token, the Admin Token Administrator (the HSM SO) will be required to install the certificate in the Admin Token. The verification and loading of the FM requires the HSM Administrator to provide the Admin Token password, enforcing the presence of the HSM Administrator during the loading operation.
NOTE The Admin partition (a.k.a. Admin Token) is not directly available to client servers using the Luna Network HSM 7. Operators of Luna Network HSM 7s must use the LunaSH hsm fm commands to load FM Certificates into the HSM Admin Token.
As previously advised, there is no pre-defined key management scheme for the private key and the certificate. One of the first things to be performed by the FM developer is to decide on the key management scheme to be used in the system.
Example Key-Management Scheme
This section outlines a sample approach to a key management scheme, which can be customized and extended.
It is recommended that the key used to sign the FM in the Adapter Build phase is not the same as the key used to sign it in the Production build phase. This would ensure that a FM in the Adapter Build or Adapter Testing phase cannot be used by end-users or customers. Additionally, the usage of a production-level FM signing key needs stricter access control requirements compared to the development signing keys. Using this key to sign FM images in Adapter Build phase would therefore make the task of development more difficult.
The easiest key management scheme for development keys on a Luna PCIe HSM 7 is to generate a new self-signed key/certificate pair in the Admin token of the target HSM. This can be done using the Thales CMU tool.
For the Luna Network HSM 7 a normal User Token should be used to hold the signing key and create the FM Certificate. The certificate can then be extracted and used with the LunaSH hsm fm load command.
There should be a production grade HSM to hold the production key/certificate pair.
The raw FM binary image must be signed using the private key generated, as discussed previously. This can be achieved using the mkfm utility. The signed FM image can then be loaded into the HSM using the ctfm utility (on Luna PCIe HSM) or the LunaSH hsm fm load command (on Luna Network HSM 7).
Contents of the Luna FM SDK package directory
When installed, the Luna FM SDK package directory (/usr/safenet/lunafmsdk Directory [Linux] or
C:\Program Files\SafeNet\LunaClient\samples\fmsdk Directory [Windows]) contains the following:
Directory | File Description |
---|---|
include/ | Header files specific to FM and FM Host Application development. These are used together with headers provided by Luna HSM SDK. |
lib/libfmsupt.a | Static libraries used for building an FM that will run in an HSM. |
samples/ | Sample FMs and FM Host Applications |
samples/fmconfig.mk | Common configuration makefile that sets up makefile and toolchain variables and rules required for building an FM. This should be included at the top of any FM's makefile. |
NOTE Samples for Functionality Modules rely on the ELDK library that is installed only for Linux. The host samples work for both Linux and Windows.
SDK Installation Tips
Set the Environment
The tools are all located in the /usr/safenet/lunaclient/bin folder so it will be convenient to add this folder to the PATH. For example:
export PATH=$PATH:/usr/safenet/lunaclient/bin
The libraries to support the tools are all located in the /usr/safenet/lunaclient/lib folder.
The Luna tools will use /etc/Chrystoki.conf to obtain the location of the libraries they need. However, the FM Test applications only use the standard system library search methods. As a result, when running FM Test applications it is convenient to add the lunaclient lib folder to the LD_LIBRARY_PATH. e.g.:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/safenet/lunaclient/lib
NOTE For Windows environments, set a search path to the libraries.
Example: for a default installation, set:
PATH=C:\Program Files\SafeNet\LunaClient\
and
LD_LIBRARY_PATH=C:\Program Files\SafeNet\LunaClient\
Adjust your path statement if you selected a non-default install path during Luna HSM Client software installation.
Protecting Data Storage of FM
When the FM is used to extend the HSM functionality, usually there would be data that needs to be protected by the HSM. Normally, this data would be stored as a Cryptoki Key Object in one of the tokens (partitions). Protecting the contents of these objects poses a problem, because, setting the SENSITIVE attribute on the object would prevent access to the data from the FM, and leaving it open would allow any PKCS#11 application on the host side to get the contents of the data.
There are two possible solutions to this problem:
Using Privilege Level
The CT_SetPrivilegeLevel function allows a simple solution to the problem stated above. The FM can make a call to temporarily obtain the rights to read sensitive object attributes.
This allows the FM designer to create and manage their keys using the tools provided with the HSM. This increases security by allowing the user access from the trusted FM, while reducing the risk from external programs.
Using the SMFS
The Secure Memory File System (SMFS) provides access to key storage area that is exclusively for the use of FM developers, the FM designer can store keys without these keys being visible through the HSMs Cryptoki interface.
The format of the keys is entirely up to the FM designer – they need not have attributes that the Cryptoki objects do.
There is no need to call C_Initialise or open sessions or search for object handles if you use the SMFS to store your keys.
FMs that store their keys in SMFS need to provide all the functions to generate, store, delete, backup and restore these keys.
The SMFS system uses a Open read/write Close paradigm.
NOTE Functionality Modules that open an SMFS file and keep the handle open should take into account the following:
>The number of SMFS file handles is a limited resource (approx 16).
>Therefore FM designers should not keep SMFS file handles.
>Instead use SMFS to do backup and restore only.
>Keep the keys in normal memory while the FM is running.
>Restore the keys from SMFS during the FM initialization by opening/reading and closing the SMFS file.
>When changes are made to the keys, then open/write/close the SMFS file to backup the changes.
Similar to the way a Luna partition cannot be used by an application until an operator has activated it by logging on to it, the SMFS cannot be used until it is Activated. SMFS Activation occurs when the HSM Security Officer or Administator issues the SMFS Activation command -
The HSM can be configured to automatically Activate on each startup, by setting the appropriate Security Policy. Other Security Policy flags affect the behavior of FMs – please refer to HSM Capabilities and Policies.
Because the HSM does not pass control to any FMs until after the SMFS is activated the FM designer can assume that the SMFS is always Activated.
Scatter Gather FM Message Dispatching
FM Message dispatching (from client to HSM) support allows for more than one request buffer, and more than one reply buffer to be presented to the HSM in one command. The message dispatch layer provides scatter-gather support to combine all the request buffers into a single data buffer, and send it to the HSM. The reply data is treated the same way, but in the reverse direction - the data is scattered into multiple reply buffers. This feature can be very useful when information to be sent to the HSM and the information received from the HSM are kept in different variables or buffers.
The scatter-gather operation on the reply buffers can behave in an unintuitive manner when the initial buffers are variable length. The device driver will start filling the host side initial buffers with the reply data and it will not place any data into subsequent buffers until the current one is completely filled. The effect of this is that the reply buffer fields may not contain the expected values when the amount of data placed in a variable length buffer is less than the maximum length of the buffer.
For example, if two reply buffers of 40 bytes each are passed to the message dispatch layer, but the actual data to be returned in each buffer is only 32 bytes, then the first 40 byte buffer will be filled with 32 bytes of data meant for the first buffer, and 8 bytes of data meant for the second buffer. The second reply buffer of 40 bytes will only contain 26 bytes of data.
This behaviour is handled via two possible cases:
>After receiving the reply, re-align the data in the buffers. The order of re-alignment must be from the last buffer to the first. In order to be able to implement this, the reply data, in its entirety, must contain enough information to determine the length of each reply block.
>Always merge the reply buffers to a single block before dispatching the request, by allocating another block, and moving data from the allocated buffer to the caller’s reply buffers. This approach makes the code more reliable.
Handling Host Processes IDs
The Luna FM SDK package allows a FM developer to determine the identity of processes sending messages to the HSM.
The functions FM_GetCurrentAppId, and FM_SetCurrentAppId allow you to know what process is sending the current message.
If your FM supports the concept of a user login then you will need to track which host processes have logged in.
You can remember which process has logged in by storing the AppId as the process successfully authenticates. When a process sends a message that requires authentication you can check to see if the process is the list of authenticated processes.
The Cryptoki system always uses the AppId to determine if a session handle or object handle is valid for the calling process.
Therefore if the FM makes Cryptoki calls while processing a request by using a session handle obtained earlier from a different request then there is a possibility that the Cryptoki call with fail with CKR_CRYPTOKI_NOT_INITIALIZES error.
This is because process A calls the FM which then calls C_Initialize and opens a Cryptoki session. Then later process B calls the FM and the FM tries to use the session handle. The Cryptoki will not recognise process B. To overcome this problem you may want to modify the AppId to a constant value that the underlying Cryptoki sees by using the FM_SetCurrentAppId calls prior to making any Cryptoki calls.
NOTE The value –1 for AppId is a suitable choice for this purpose.
C_CloseAllSessions - Notes
Special consideration should be made of the C_CloseAllSesions function call.
Because the FM and the calling process share the same AppID (see previous section) then HSM considers any session opened using C_OpenSession() by either the Host side application or the FM (on behalf of the calling process), to be owned by the same Application.
So if either the FM or the Application calls C_CloseAllSessions then all sessions owned by that AppId are closed.
An example illustrates this:-
>The Application opens a session and gets session handle 1.
>The Application calls the FM and the FM opens a session it gets session 2.
>The HSM now thinks this application owns two sessions.
>If either the Application or the FM calls C_CloseAllSession then both sessions will be closed.
A well designed solution will clean up its own sessions with C_CloseSession() and avoid the use of C_CloseAllSessions().
Memory Alignment Issues
The PowerPC processor in the Luna PCIe HSM 7 does not require fully aligned memory access, however unaligned access incurs a performance cost.
Memory Endian Issues
The processor in the Luna PCIe HSM 7 is big endian, where the processors in PTK based PSIe and PSG are little endian.
It is recommended that FM developers use the provided endian macros to encode all messages in network byte order. By using the endian macros on both host and FM, endian differences between host and HSM are not an issue.
The utility endian macros, such as fm_htobe16, are provided in the header file fm_byteorder.h.
Compiling FMs
The sample FMs provided in the Luna FM SDK package include makefiles to script the compiling and linking of the sample FMs. These makefiles are written to be compatible with the GNU make utility.
When you write your own FM you can start by copying one of the sample FMs. You can remove the unnecessary code and substitute in new code on an as-needed basis. The FM makefile will also need to be modified to match the set of source files for the new FM.
The compiler is available at this location:
/opt/eldk-5.6/powerpc-4xx/sysroots/i686-eldk-linux/usr/bin/powerpc-linux/powerpw-linux-gcc
However, if you do not want to use the GNU make utility, the following sections will give basic instructions on what actions are required for compiling and linking FMs.
Include Path
The -I option is required to tell the compiler where to get the Luna FM SDK package header files.
To build a Luna FM
Use these folders in the following order:
1./usr/safenet/lunaclient/include
2./usr/safenet/lunafmsdk/include
3./usr/safenet/lunafmsdk/include/fm/hsm
4./usr/safenet/lunafmsdk/include/fm/host
PPO Compatibility INCLUDE Files
FMs written for the PPO SDK will have specific Thales ProtectToolkit (PTK) specific identifiers which are not part of the Luna FM SDK package. The Luna FM SDK package includes compatibility headers which will ease the porting of PPO source to a Luna FM environment.
To build a Luna FM from PPO FM source
Use these folders in the following order:
1./usr/safenet/lunaclient/include
2./usr/safenet/lunafmsdk/include
3./usr/safenet/lunafmsdk/include/fm/ppo-compat
4./usr/safenet/lunafmsdk/include/fm/ptk-compat
DEFINES
These are the minimum –D Flags required when compiling a FM with Eldk.
# OS_LINUX - needed by cryptoki header files (cryptoki_v2.h) # _GNU_SOURCE -- required to specify correct c runtime lib support # DISABLE_CA_EXT -- tell cryptoki_v2.h not to include Luna Extension header (not used in FM) # IS_BIG_ENDIAN -- defines the hsm endian is big - only required if using PPO compat headers DEFINES += -DOS_LINUX -DIS_BIG_ENDIAN -D_GNU_SOURCE -DDISABLE_CA_EXT
C_Flags
The following are the minimum C FLags required when compiling a FM:
-fPIC -ffreestanding -std=c99
L_Flags
The FM is linked as a shared object which exports some symbols but imports none (including the standard C runtime library).
Only two libraries are required to link the FM: the libfmsupt.a static library from Luna FM SDK package and the libgcc.a from /opt/eldk-5.6. As a result, these linkage flags must be passed to the GNU compiler.
L_FLAGS = -shared -zdefs -nostdlib -WI, -static -WI, --gc -sections -L /usr/safenet/lunafmsdk/lib -lfmsupt -lgcc
Building Applications that Talk to FMs
The Sample FMs provided in the FM SDK include makefiles to script the compiling and linking of the test applications that communicate with the sample FMs.
These makefiles are written to be compatible with the GNU make utility on Linux.
When you write your applications to communicate with your own FM you can start the design by copying one of the sample FMs test application source and strip out the code not needed and add new code as appropriate.
The host/makefile will also need to be modified to match the set of source files of the new FM.
However, if you do not want to use the GNU make utility the the following sections will give basic instructions on what options are required for compiling and linking applications to communicate to FMs.
INCLUDE PATH
The -I option is required to tell the compiler where to get the Luna Cryptoki and MD API header files.
To build a Luna FM Application
Include this folder:
>/usr/safenet/lunafmsdk/include
PPO Compatibity INCLUDE Files
Applications written for PTK and/or the PPO SDK will reference specific identifiers which are not part of the Luna FM SDK package. The Luna FM SDK package includes compatibility headers which will ease the porting of PPO/PTK source to the Luna FM SDK environment.
To build an application from PPO/PTK source
Use these folders in the following order:
1./usr/safenet/lunafmsdk/include/fm/ppo-compat
2./usr/safenet/lunafmsdk/include/fm/ptk-compat
3./usr/safenet/lunaclient/include
4.<other_folders>
L_FLAGS
There are two libraries which give an application access to the HSM:
>/usr/safenet/lunaclient/lib/libCryptoki_64.so
>/usr/safenet/lunaclient/lib/libethsm.so
You can design the application to load the shared libraries at runtime or load time.
Runtime
Use the dlopen() and dlsym() to load libCryptoki2_64.so and/or libethsm.so and fetch entry points as required.
The path to the libraries can be controlled by configuration implemented in the application.
Load Time
Link the application against the shared libraries when linking the application.
When running the application you need to use the LD_LIBRARY_PATH environment variable to point to /usr/safenet/lunaclient/lib or use that -rpath option to tell the application where to find the libraries.
Troubleshooting
SMFS Activation Delay
On FM-enabled HSMs with SMFS auto-activation enabled, there is a delay of approximately 2 seconds for the SMFS to activate after an HSM or driver reboot. For scripted operations, this could cause a host app to fail if it queries the FM immediately after a reboot.
If you encounter this issue, include a 2-second sleep in the script between the reboot and the first FM query.