2

I ran into some issues writing a small test programme using the cryptoki library. I want (have) to get hold of the RSA private key (all its parameters). I thought about either generate keys and then extract the parameters or use already generated parameters to set the keys manually. So far, I don't get any of this working. Code is at the end of the post.


Extraction

I know that there is the C_GetAttributeValue() with which I can extract attributes such as the public exponent or the modulus. That works for both public and private key objects but I get CKR_ATTRIBUTE_SENSITIVE error for when I try to extract private parameters from the private key object. Is there a way to extract these attributes? Can/Do I have to set certain parameters when logging into a session or during initialising?

Setting Keys manually

My second approach was to read key material (generated with OPENSSL) from a file and use that for generating key objects with C_CreateObject(). The file contains all RSA parameters (n,e,d,p,q,dmp1,dmq1,iqmp). After reading, I convert them from ASCII to hex representation and store them in a CK_BYTE[]. So far so good. Now, when I pass all this to the C_CreateObject() in order to create a private key I receive a CKR_ATTRIBUTE_VALUE_INVALID error message. Creating a public key object the same way with the public parameters works. I verified that using C_GetAttributeValue() on the created public key object. What am I missing for generating a private key object if this is even possible this way? I suppose that C_GenerateKeyPair() always generates new keys no matter whether key material is provided or not, right?


C Code

This is what I try to create the private key object with:

CK_OBJECT_HANDLE hPrivateKeys[NUMKEYS];
CK_KEY_TYPE kType= CKK_RSA;
CK_OBJECT_CLASS kClass = CKO_PRIVATE_KEY;
CK_BYTE id[] = {123};
CK_UTF8CHAR label[] = "An RSA private key object";

// sn,sd,se, etc contain the length of the respective parameter
CK_ATTRIBUTE privateKeyTemplate[] = {
            {CKA_CLASS, &kClass, sizeof(kClass)},
            {CKA_KEY_TYPE, &kType, sizeof(kType)},
            {CKA_TOKEN, &false, sizeof(false)},
            {CKA_PRIVATE, &false, sizeof(false)},
            {CKA_SENSITIVE, &false, sizeof(false)},
            {CKA_EXTRACTABLE, &true, sizeof(true)},
            {CKA_ID, id, sizeof(id)},
            {CKA_SUBJECT, NULL_PTR, 0},
            {CKA_DECRYPT, &true, sizeof(true)},
            {CKA_SIGN, &true, sizeof(true)},
            {CKA_LABEL, label, sizeof(label)-1},
            {CKA_ID, id, sizeof(id)},
            {CKA_MODULUS, modulus, sn},
            {CKA_PUBLIC_EXPONENT, publicExponent, se},
            {CKA_PRIVATE_EXPONENT, privateExponent, sd},
            {CKA_PRIME_1, prime1, sp},
            {CKA_PRIME_2, prime2, sq},
            {CKA_EXPONENT_1, exponent1, sdmp1},
            {CKA_EXPONENT_2, exponent2, sdmq1},
            {CKA_COEFFICIENT, coefficient, siqmp}
    };

    CK_ATTRIBUTE publicKeyTemplate[] = {
            {CKA_ENCRYPT, &true, sizeof(true)},
            {CKA_VERIFY, &true, sizeof(true)},
            {CKA_WRAP, &true, sizeof(true)},
            {CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)},
            {CKA_PUBLIC_EXPONENT, publicExponent, se},
            {CKA_MODULUS, modulus, sn}
    };

rv = pFunctionList->C_CreateObject(hSession, privateKeyTemplate, NUM_ELEM(privateKeyTemplate), &hPrivateKeys[j]);
Rick
  • 121
  • 14

1 Answers1

0

Your idea of generating a key pair and then reading it out is fine, you should however set the attribute CKA_SENSITIVE to false in the template of the private key. Note that it always depends on the token itself if such functionality is supported.

Usually when extracting private key information from a token you want to have it encrypted. Encryption of keys is called wrapping, and the possible extraction of sensitive information is managed by the CKA_EXTRACTABLE attribute.

After reading, I convert them from ASCII to hex representation and store them in a CK_BYTE[].

The PKCS#11 token interface specifies precisely how to encode / decode attributes. Just trying formats haphazardly is not going to give any results.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • I set the CKA_SENSITIVE attribute to false. Still not working. I don't want to wrap a key, I want to be able to read the key values so I know d,p,q, etc. What does "Note that it always depends on the token itself if such functionality is supported." mean? Is there a way to enable that support? – Rick May 17 '15 at 11:43
  • You might be able to use wrapping to extract the key and they unwrap. PKCS#11 is an API for C applications. A PKCS#11 token must contain all the API methods, but it may not actually implement all the possible functionality. E.g. smart cards usually restrict themselves to searching and signature generation/decryption with RSA keys. – Maarten Bodewes May 17 '15 at 14:46
  • Hi RIck, were you able to find a solution to this? – Paul Schimmer Jul 20 '21 at 12:56
  • No, sorry. I were not – Rick Jul 22 '21 at 13:59