Module Keys

A module key:

  • is a DES3 or AES key

  • is not an application key

  • does not have an ACL

  • is persistent across module reset (but not reinitialization)

  • is identifiable by the hash of the key material (usually; not true for null module keys)

  • is given a name starting "KM"

  • can be used to protect a logical tokens and keys

Some module keys are constructed entirely within the module, for example KM0. Others are loaded (normally only during initialization) via the SetKM command.

Module keys are erased by Cmd_InitialiseUnit and Cmd_InitialiseUnitEx. Moreover the persistent storage within the HSM used for module keys is encrypted under a key unique to the HSM and installed firmware, putting them beyond use after an upgrade.

KM0

KM0 is:

  • an AES key (formerly DES3)

  • generated by Cmd_InitialiseUnit and Cmd_InitialiseUnitEx (destroying the old KM0 upon reinitialization; so KM0 blobs are not suitable for long-term key protection)

KM0 appears in the slot 0 in the internal array of module keys (and therefore the first slot in the list of module key hashes returned by Cmd_GetKMList), hence the name.

If an application key is to be blobbed under any module key other than KM0, then AllowNonKm0 must appear in its ACL.

KM0 is an AES key even if the module is in a DES3 security world.

Null module keys

KMNULL is:

  • for a given key type, constant

  • well-known

    • for DES3, the key material is 0x010101…​

    • for AES, the key material ix 0x000000…​

  • identifiable in ACLs by a 'special' hash

    • for DES3, the hash is 0x000000…​

    • for AES, the hash is 0x010000…​

  • built into the module firmware

  • used to 'protect' logical tokens that need to be read during module initialization (LTNSO and LTM), since no other confidentiality key is available at this point

  • not capable of providing any confidentiality

If an application key is to be blobbed under a logical token protected by a null module key, AllowNullKMToken must appear in its ACL. Normally this would only be used for KNSO and KM, since no other module key is available when they are to be created or loaded.

KMWK

The underlying null module key values are also used as KMWK, the "well known module key". Which of them is used depends on the ciphersuite.

  • In DLf1024s160mDES3, DLf1024s160mRijndael and DLf3072s256mRijndael, KMWK is the DES3 null module key (with nCore key hash of this key is 1d572201be533ebc89f30fdd8f3fac6ca3395bf0)

  • In other worlds KMWK is the AES module key (with nCore key hash c2be99fe1c77f1b75d48e2fd2df8dffc0c969bcb)

KMWK is installed as a module key, exempting it from the requirement for AllowNullKMToken in ACLs.

To load KMWK into the module a (constant!) blob of KMWK under itself is used.

Module Key API Calls

  • Cmd_SetKM allows an application key to be stored as a module key. The application key must have the UseAsKM permission in its ACL. The sworld implementation uses this command during world creation and world loading to install KM as a module key.

  • Cmd_RemoveKM removes a module key from persistent storage. KM0 cannot be removed.

  • Cmd_GetKMList retrieves a list of the hashes of all module keys.

  • Cmd_InitialiseUnit and Cmd_InitialiseUnitEx erase all module keys (including KM0).

Example

>>> print conn.transact(nfpython.Command(['GetKMList', 0, 1]))
Reply.cmd= GetKMList
     .status= OK
     .flags= 0x0
     .reply.flags= KNSOset
     .hknso= 787720a1 e305a5af 6c8564af 3f6bfe55 122a733d
     .hkms[0]= df4d2a87 e0eca861 a1063bd1 dcaa9b1a 87bf83f6
     .hkms[1]= 1d572201 be533ebc 89f30fdd 8f3fac6c a3395bf0
     .hkms[2]= 8fd82ce3 2e58f8e4 b559dddb 62de8cf6 5e66ce58

In the output:

  • hkms[0] is KM0 (see KM0).

  • hkms[1] is KMWK (see KM0). This ends up in this position due to the order things happen in security world creation. Applications shouldn’t assume that this is always true.

  • hkms[2] is KM in this example, see KM (Security World Module Key). Again the numbering is a result of the order in which security world creation is performed; applications shouldn’t assume that it is always true.

Compare this with the output of nfkminfo:

$ nfkminfo
World

generation 2
state 0x1fa70000 Initialised Usable Recovery PINRecovery !ExistingClient RTC NVRAM
  FTO !AlwaysUseStrongPrimes SEEDebugForAll
n_modules 1
hknso 787720a1e305a5af6c8564af3f6bfe55122a733d
hkm 8fd82ce32e58f8e4b559dddb62de8cf65e66ce58* (type Rijndael)
hkmwk 1d572201be533ebc89f30fdd8f3fac6ca3395bf0*
hkre a7ae9935f04f4680c3046a02c7fa838dd3ffd3ed
...