Integration overview
Integrating NanoSec code into your devices or applications boosts security and efficiency. This straightforward process embeds advanced security protocols into your software, providing strong cryptographic functions and secure communication channels.
Device integration steps
Integrating NanoSec into your devices involves a series of steps, some of which may be optional depending on your specific deployment needs. Below is a general guide to help you through the device integration process.
Step 1: Add NanoSec software
Start by adding the NanoSec software to your application’s development environment. For detailed instructions on building the necessary components of the TrustCore SDK, refer to the Building TrustCore SDK Components section.
Step 2: Port the SDK
If your operating system doesn’t have a pre-configured TrustCore SDK port, you will need to edit the appropriate abstraction files to port the SDK to your operating system. For guidance, see Porting TrustCore SDK Code.
Step 3: Configure SDK compilation flags
Decide which products (like IKE and IPsec) and functions (such as debugging and examples) to include in the TrustCore SDK executable. This is done by setting the appropriate compilation flags. For instance, to integrate the IKE server, define the __ENABLE_MOCANA_IKE_SERVER__
flag. For more details, check the sections under Building TrustCore SDK Components, specifically Compilation Flags and Enabling NanoSec MOBIKE Support.
Step 4: Build executables
Create the executables and loadable modules. Verify that the TrustCore SDK code can execute on the operating system as described in Building TrustCore SDK Components.
Step 5: Integrate SDK functions
Integrate calls within your application’s code for TrustCore SDK initialization and shutdown. Set up threads for any required TrustCore SDK server components as outlined in NanoSec IKE Integration.
Step 6: Implement keying and authentication
Include calls to TrustCore SDK NanoSec functions for keying, authentication, message processing, and, optionally, certificate management. See NanoSec IPsec Integration for more details.
Step 7: Customize IKE configuration
Add calls to customize IKE configuration for authentication information and application callbacks as described in Dynamic Configuration.
Step 8: Set up security policies
Set up security policies and, if necessary, add manual keying between a device and its peer. For more information, refer to Provisioning.
Step 9: Optimize performance
To maximize the performance of your integration, follow the tuning guidelines provided in Tuning NanoSec IPsec.
Application integration steps
To integrate NanoSec into your application, follow these steps, keeping in mind that some tasks may be optional based on the specific needs of your deployment.
Step 1: Initialize and shutdown routines
Begin by integrating common code initialization and shutdown routines. Add the relevant calls in your application as demonstrated in the /src/examples/mocana_example.c
sample module. For further details, see TrustCore SDK Code Initialization –link–.
Step 2: Implement IKE functionalities
Add calls within your application to handle NanoSec’s IKE functionalities. This includes initialization, communication, message processing, and the proper shutdown of IKE operations. For further details, see NanoSec IKE Integration –link– and Enabling NanoSec MOBIKE Support –link–.
Step 3: Enable IPsec operations
Enable IPsec operations such as initialization, packet fragmentation, reassembly, and processing. Integrate the corresponding NanoSec function calls within your application’s code as detailed in NanoSec IPsec Integration –link–.
Step 4: Incorporate certificate management
If your application does not already manage certificates, incorporate TrustCore SDK’s certificate management functions to handle certificate validation. For further details, see Using Certificates –link–.
Step 5: Proper shutdown sequence
Ensure that your application adheres to the correct shutdown sequence for both IPsec and IKE by integrating the appropriate shutdown calls within your code. For best practices and detailed steps, see Shutdown Sequence –link–.
TrustCore SDK code initialization
Applications should perform the common TrustCore SDK code initialization and shutdown work, as shown in the src/examples/mocana_example.c sample module. In particular, make the following function calls and perform the following procedures:
MOCANA_initMocana: Initialize the TrustCore SDK common code base (logging, random number generator, and so on).
MOCANA_initLog: Optionally, register a callback function to the TrustCore SDK logging system.
Create threads for all required TrustCore SDK component servers (e.g., the NanoSec IKE server).
Implement a status-checking loop that runs and sleeps as long as an application running flag is true.
MOCANA_freeMocana: Release memory that was allocated by MOCANA_initMocana.
NanoSec IKE integration
To integrate NanoSec IKE into an application, add calls to NanoSec functions for IKE initialization, establishing SAs (security associations), message processing, and IKE shutdown, as shown in the src/examples/ike_example.c sample module.
In particular, the following functions and tasks should be performed:
IKE_init
Initialize NanoSec IKE’s internal context.A loop (that runs until a shutdown message or flag is received) to continuously accept connections and process packets:
IKE_msgRecv (for IKE v1) or IKE2_msgRecv (for IKE v2)—Listen for incoming IKE UDP packets.
A timer to track the receipt of UDP packets; if the IKE listener becomes idle (that is, a message isn’t received for a preconfigured amount of time), call IKE_msgIdle.
Enable NanoSec MOBIKE support
NanoSec IKE includes full support for MOBIKE with no need for additional application coding. Simply follow these guidelines:
When building NanoSec IKE, ensure the following flags are defined in moptions.h:
__ENABLE_MOBIKE__ __IKE_MULTI_HOMING__
Be sure to use IKEv2 (not IKEv1, which does not include MOBIKE support).
Implement the application so that the mobile peer is the initiator.
The example code in src/examples/ike_example.c shows how to create multiple interfaces. Check to see whether an interface is active, and if it is not, use the next interface. This approach can be adapted to updating the SA because of an IP address change caused by a mobile client.
Implement the initiator so that it calls IKE2_keyUpdate whenever its IP address or interface changes, thereby enabling the connected peer to update the SA and maintain the connection.
Shutdown sequence
To cleanly stop and shut down IPsec and IKE, the following calls should be made in this order:
Stop IPsec:
IPSEC_flush
Release rules from the SPD (Security Policy Database) and keys from the SADB (Security Association Database) within the IPsec stack.RTOS_sleepMS(5000); /* IKE notifies peers of dead IPsec SAs */
Stop the IKE server. In the sample code (
ike_example.c
), the while loop variable,isBreakSignalRequest
, is set toTRUE
.
Stop IKE:
IKE_shutdown
Shutdown the IKE stack; call after exiting the while (!isBreakSignalRequest) loop.RTOS_sleepMS(2000);
Wait for IKE sockets to finish data transmit.A function to close any open sockets.
Any additional clean up, such as
MOCANA_freeMocana
.
NanoSec IPsec integration
NanoSec IPsec integration entails adding calls to an application for NanoSec initialization and packet fragmentation and reassembly, as shown in the TrustCore SDK sample module src/examples/ipsec_example.c
.
The following calls should typically be inserted after the application’s TCP/IP initialization functions (which come before any IPsec processing routines):
IPSEC_init
Initialize IPsec internal structures and counters.
The next step of IPsec integration entails adding calls to IPSEC_apply
and IPSEC_permit
, to perform packet fragmentation and reassembly. Your network stack integration requirements determine how and where to add the packet processing.
Bump in the Stack (BITS) insertion
The figure below shows how IPsec fits within a typical IP stack. Integrating NanoSec involves making a few minor changes to the IP stack.
To integrate NanoSec IPsec, insert two small code blocks near the bottom of an IP stack. As shown in Figure 10 above, IPsec is inserted between the lowest layer (the native packet fragmentation layer) and the IP routing layer.
To insert a bump in the stack:
Trace up the stack from the interface driver.
Examine the source code, looking for calls to functions that fragment and reassemble the message (for example, functions with “frag” or “reassemble” in their names; in files named frag.c or reassembly.c, etc).
Add the following calls to NanoSec functions immediately after the calls identified in step 2:
IPSEC_apply
for outgoing packets.IPSEC_permit
for incoming packets.
If an outbound packet requires applying IPsec security protection, the packet may grow slightly because of HMAC (hash message authentication code, which provides data integrity protection) and message padding (for block ciphers encryption); therefore, before calling IPSEC_apply, either ensure that the IP packet’s buffer being processed is large enough (typically 65 bytes of padding for transport mode, and 85 bytes for tunnel mode), or pass in a buffer to use if the packet buffer grows. In the latter case, the original IP packet buffer being processed should be discarded to avoid a memory leak.
Below Binary Stack (BBS) implementation
Although not as efficient in terms of CPU and memory usage as the recommended BITS integration, NanoSec can be integrated with binary TCP/IP stacks. In this case, NanoSec IPsec code sits between the interface device driver and the binary TCP/IP stack, as shown in Figure 11 below, and provides IP fragmentation and reassembly code. This method is useful in the following situations:
The application has no direct access to TCP/IP code and the native TCP/IP functionality cannot be modified.
To avoid the complexity of working directly with TCP/IP code.
To allow for future replacement of the TCP/IP stack.
Important
For BBS implementations, fragmentation should not be performed by the TCP/IP stack. Either disable its fragmentation layer or set its MTU (maximum transmission unit) to the maximum packet size. If the MTU is set to the maximum packet size, the TrustCore SDK stack fragments the secured IP packets to the appropriate MTU size for the network interface.
For BBS implementations, fragmentation should not be performed by the TCP/IP stack. Either disable its fragmentation layer or set its MTU (maximum transmission unit) to the maximum packet size. If the MTU is set to the maximum packet size, the TrustCore SDK stack fragments the secured IP packets to the appropriate MTU size for the network interface.
To process outgoing packets, the BSP (board support package) output driver needs to be customized to add the following calls:
IPSEC_apply
TrustCore SDK NanoSec fragmentation code (methods with “IPsec_frag” in their name)
Methods to transmit the data; for example, through a device’s Ethernet interface
To process incoming packets, customize the BSP input interface to add the following calls:
TrustCore SDK NanoSec reassembly code
IPSEC_permit
Methods to pass data up the stack
Packet filtering
For BITS implementations, the packet filtering mechanism provided by the target platform can be used instead of modifying the TCP/IP stack directly. For example, on Linux, packets can be intercepted by netfilter hooks.
Using certificates
Certificate verification is a critical part of security authentication. Certificate verification can be implemented by using proprietary certificate management functions or those provided by the TrustCore SDK certificate management API.
The NanoSec functions of interest are:
IKE_initServer
Configure NanoSec IKE for PSK or a given host certificate.IKE_initCertChain
Configure NanoSec IKE to use a host certificate chain.IKE_initTrustAnchor
Configure NanoSec IKE to use a set of trust anchors (i.e., CA certificates) for authenticating peer certificates.
Next, calls need to be added to the TrustCore SDK certificate management functions, as modeled in the TrustCore SDK sample module, src/examples/ca_mgmt_example.c
.