The architect wants to create a single, custom firmware sub-function that will generate an HMAC for some data, based on a specific digest (SHA512 or SHA2-256 or ...), a secret key derived from some input data, and another key which is stored according to CXI. The CXI key may be passed in either by name/group/spec (to look up an internal key), or as an encrypted 'external key blob'.
Additionally, they may also want to pass in a flag value, that determines how the key should be treated.
The requirement to pass in a key is common, but best-practice is to not define at design time what format the key must be in. Possibilities include a CXI normal 'name, group and spec' identifier, or a key blob which may or may not be wrapped, or it may be some third party or internal format. And, in many cases, the architect may not even know up front, how the application engineer will implement things on the host.
"As a convention" means for this example. You may have other conventions or requirements.
A reasonable description for the key data, then, is:
-
A flag (a 1-byte integer), which may encode different options
-
A key Name (using a limit of 32 characters as a convention)
-
A CXI key Group (using a limit of 32 characters as a convention)
-
A key specifier (a 4-byte integer)
-
A data "blob" (an unstructured byte buffer of indeterminate length, generally no more than 4k in size)
Different patterns will match the above requirements. Two such are u1c32c32u4v2 and u4v1v1u4v4. For this walk-through, we will use the u1c32... variant. Patterns and their use are described below.
For the use case, then what the architect might need is:
-
The CXI Key (
u1c32c32u4v2)-
By reference, or
-
By blob
-
-
MAC algorithm flags (
u4)-
Used to select specific functionality within the sub-function
-
-
KDF Data (
v1)-
No more than 256 bytes, and
-
-
Data (
*, ie the remainder)-
The data to process.
-
The final pattern is then u1c32c32u4v2u4v1*.
The size of a single packet to/from the HSM is limited to 256Kb, including any overhead. If your methods will require more input or output data than that, you will need to develop a method to chunk data, via some sort of 'first, continue, last' methodology.
Per standard SDK SFC design methodology, the developer might create the following SFC method stub, given the u1c32... pattern:
HMAC/CMAC Sub-Function
|
|
How cmds_scanf works and what it does is covered below. For the reference documentation, see .\SDK\doc\mdl_CMDS.pdf in the SecurityServer installation directory.
The call to cmds_scanf will perform different runtime checks on the input data, on the expected number of fields in the cmd struct (computed from the input pattern), and so on, to ensure that the byte buffer received is at least reasonably well-formed based on expectations. If the return is without error, then:
-
cmd.flags (unsigned integer) value is equal to the first byte of p_cmd,
-
cmd.keyName points at p_cmd+1,
-
cmd.keyGroup points at p_cmd+1+32,
-
cmd.l_blob value is equal to the length of cmd.p_blob (and may be zero)
-
cmd.p_blob points at the first relevant byte of the p_blob,
-
and so on.
The above description covers the case of serialized data arriving at the SFC.
Without the tooling provided, at this point a (host application) programmer would need to develop methods to serialize their host data in either C++ or Java (for use on the host), and may also want to provide a serialization method in C, which could be used on the HSM also -- as the pattern might also be used to describe data being returned (from this or some other SFC).
The tools described by this document use the same pattern as supplied to cmds_scanf, to provide all the missing pieces: Host code object classes in different languages, and HSM code in C, for marshalling data suitable for use with the pattern, as well as test code and other artifacts.
The tools also do not assume that a pattern is an input or output pattern -- when a pattern is compiled, code is generated that allows the pattern to be used immediately for either sending data to the CryptoServer, or getting data back.