CKM_BIP32_MASTER_DERIVE

Supported Operations

Encrypt and Decrypt No
Sign and Verify No
SignRecover and VerifyRecover No
Digest No
Generate Key/Key-Pair No
Wrap and Unwrap No
Derive Yes
Available in FIPS Mode No

Key Size Range (bits) and Parameters

Minimum 64
Maximum 571
Parameter CKM_BIP32_MASTER_DERIVE_PARAMS

Description

Generates a BIP32 Master node key pair from a generic secret.

The BIP algorithm requires a random input for the key generation mechanism. This is provided by the C_DeriveKey's base key, which must have the following characteristics:

>CKK_GENERIC_SECRET -- using any other base key will result in an error (CKR_KEY_TYPE_INCONSISTENT)

>128-512 bits of random data -- using a seed outside of this range will result in an error (CKR_BIP32_MASTER_SEED_LEN_INVALID)

CAUTION!   To keep the BIP32 master key pair secure, restrict the generic secret key to CKM_BIP32_MASTER_DERIVE operations or immediately delete it after the master key pair is derived. Restrict operations by including --mech-list=BIP32_MASTER_DERIVE in the ctkmu command that is used to generate the key. For example, run the following ctkmu command:

ctkmu c -tgs -z128 --mech-list=BIP32_MASTER_DERIVE -nbip32seed -aPTR

Refer to Samples for a code example of creating a known seed.

This mechanism has a parameter, a CKM_BIP32_MASTER_DERIVE_PARAMS structure, defined as follows:

typedef struct CK_BIP32_MASTER_DERIVE_PARAMS 
{
    CK_ATTRIBUTE_PTR pPublicKeyTemplate;
    CK_ULONG ulPublicKeyAttributeCount;
    CK_ATTRIBUTE_PTR pPrivateKeyTemplate;
    CK_ULONG ulPrivateKeyAttributeCount;
    CK_OBJECT_HANDLE hPublicKey;
    CK_OBJECT_HANDLE hPrivateKey;
} CK_BIP32_MASTER_DERIVE_PARAMS;
 

The fields of this structure are defined as follows:

pPublicKeyTemplate Points to the key attributes for the public key.
ulPublicKeyAttributeCount States the number of attributes in the public key template.
pPrivateKeyTemplate Points to the key attributes for the private key.
ulPrivateKeyAttributeCount States the number of key attributes in the private key template.
hPublicKey Returns the public object handle after a successful key derivation.
hPrivateKey Returns the private object handle after a successful key derivation.

If the attribute count is set to zero or the template is set to NULL, the public or private key will not be generated.

If both attribute count properties are set to zero and/or both key templates are set to NULL, an error will result (CKR_MECHANISM_PARAM_INVALID).

The following restrictions apply to both templates:

>The CKA_KEY_TYPE value must be CKK_BIP32. Using any other key type will result in an error (CKR_TEMPLATE_INCONSISTENT).

>The only allowable curve for BIP32 is secp256k1. Setting an ECC curve will result in an error (CKR_TEMPLATE_INCONSISTENT).

>If the public key generated from the specified seed is invalid, an error will result (CKR_BIP32_MASTER_SEED_INVALID).

NOTE   Both the public and private keys must have the CKA_DERIVE attribute enabled, or the generated key pair cannot be used for key derivation.

Samples

Seed Generation

The code sample below demonstrates the creation of a known seed.

static CK_RV createSeed(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE *hSeed)
{
    CK_RV             rv         = CKR_OK;
    CK_BBOOL          yes        = TRUE;
    CK_NUMERIC        kt         = CKK_GENERIC_SECRET;
    CK_OBJECT_CLASS   objClass   = CKO_SECRET_KEY;
    CK_MECHANISM_TYPE mechlist[] = {CKM_BIP32_MASTER_DERIVE};
    CK_BYTE           seed[]     = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
    };
    CK_ULONG sLen = sizeof(seed);

    CK_ATTRIBUTE keyTemplate[] = {
        {CKA_KEY_TYPE,          &kt, sizeof(kt)},
        {CKA_CLASS,             &objClass, sizeof(objClass)},
        {CKA_TOKEN,             &yes, sizeof(yes)},
        {CKA_SENSITIVE,         &yes, sizeof(yes)},
        {CKA_DERIVE,            &yes, sizeof(yes)},
        {CKA_MECHANISM_LIST,    mechlist, sizeof(mechlist)},
        {CKA_VALUE,             seed, sizeof(seed)},
        {CKA_VALUE_LEN,         &sLen, sizeof(sLen)},
    };
    CK_COUNT nattr = (sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE));

    rv = C_CreateObject(hSession, keyTemplate, nattr, hSeed);
    return rv;
}

CK_RV generateMasterKeyPair(
    CK_SESSION_HANDLE hPrivateSession, CK_OBJECT_HANDLE hSeed,
    CK_OBJECT_HANDLE &hPubKey, CK_OBJECT_HANDLE &hPriKey)
{
    CK_RV        retCode    = CKR_OK;
    CK_BYTE      yes        = TRUE;
    CK_NUMERIC   kt         = CKK_BIP32;
    CK_MECHANISM deriveMech = {CKM_BIP32_MASTER_DERIVE, NULL_PTR, 0};

    CK_OBJECT_HANDLE              tmpHandle;
    CK_BIP32_MASTER_DERIVE_PARAMS BIP32_Params;

    CK_ATTRIBUTE pubKeyTemplate[] = {
        {CKA_DERIVE, &yes, sizeof(yes)},
        {CKA_KEY_TYPE, &kt, sizeof(kt)},
    };

    CK_ATTRIBUTE priKeyTemplate[] = {
        {CKA_DERIVE, &yes, sizeof(yes)},
        {CKA_KEY_TYPE, &kt, sizeof(kt)},
    };

    BIP32_Params.pPrivateKeyTemplate        = priKeyTemplate;
    BIP32_Params.ulPrivateKeyAttributeCount = (sizeof(priKeyTemplate) / sizeof(CK_ATTRIBUTE));
    BIP32_Params.pPublicKeyTemplate         = pubKeyTemplate;
    BIP32_Params.ulPublicKeyAttributeCount  = (sizeof(pubKeyTemplate) / sizeof(CK_ATTRIBUTE));

    deriveMech.pParameter     = &BIP32_Params;
    deriveMech.usParameterLen = sizeof(BIP32_Params);

    retCode = C_DeriveKey(hPrivateSession, &deriveMech, hSeed,
                          priKeyTemplate, (sizeof(priKeyTemplate) / sizeof(CK_ATTRIBUTE)),
                          &tmpHandle);
    hPubKey = BIP32_Params.hPublicKey;
    hPriKey = BIP32_Params.hPrivateKey;
    return retCode;
}

BIP32 Master Key Derivation

The code sample below demonstrates the derivation of a BIP32 master key pair.

CK_RV generateMasterKeyPair(
      CK_SESSION_HANDLE hPrivateSession
    , CK_OBJECT_HANDLE hSeed
    , CK_OBJECT_HANDLE& hPubKey
    , CK_OBJECT_HANDLE& hPriKey
    )
{
    CK_RV retCode = CKR_OK;
    CK_BYTE no = 0;
    CK_BYTE yes = 1;
 
    CK_NUMERIC kt = CKK_BIP32;
    CK_OBJECT_HANDLE tmpHandle;
 
    CK_ATTRIBUTE pubKeyTemplate[] = {
        {CKA_DERIVE,      &yes,         sizeof(yes)},
        {CKA_KEY_TYPE, &kt,sizeof(kt)  }
    };
 
    CK_ATTRIBUTE priKeyTemplate[] = {
        {CKA_DERIVE,      &yes,         sizeof(yes)},
        {CKA_KEY_TYPE, &kt,sizeof(kt)  }
    };
 
    CK_MECHANISM     deriveMech = { CKM_BIP32_MASTER_DERIVE , NULL_PTR, 0 };
    CK_BIP32_MASTER_DERIVE_PARAMS BIP32_Params;
 
    BIP32_Params.pPrivateKeyTemplate = priKeyTemplate;
    BIP32_Params.ulPrivateKeyAttributeCount = (sizeof(priKeyTemplate) / sizeof(CK_ATTRIBUTE));
    BIP32_Params.pPublicKeyTemplate = pubKeyTemplate;
    BIP32_Params.ulPublicKeyAttributeCount = (sizeof(pubKeyTemplate) / sizeof(CK_ATTRIBUTE));
 
    deriveMech.pParameter = &BIP32_Params;
    deriveMech.usParameterLen = sizeof(BIP32_Params);
 
    retCode = C_DeriveKey(hPrivateSession, (CK_MECHANISM_PTR)&deriveMech, hSeed,
        (CK_ATTRIBUTE_PTR)priKeyTemplate, (sizeof(priKeyTemplate) / sizeof(CK_ATTRIBUTE)),
        &tmpHandle);
    hPubKey = BIP32_Params.hPublicKey;
    hPriKey = BIP32_Params.hPrivateKey;
    return retCode;
}
 

Return to ProtectToolkit-C Mechanisms