I am trying to import a base64 representation of private key into safenet dongle.
Example Private key:
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA3VLpIpck/ExTwh5Ac118symULpg2KjgO4AgwtPeQa3XvayPJlY
jBmrj7ZMjzdMu4YKQt8E9j7lcs8m2nDfV0Uloy840JKHdCpSm6HJf8xBqxds4KyC3m
horNk+NvOYrWf4OnOtcuu9Fs1m7t5pQVlWysr8kkBNSu/NIisZpDTtIddo4S/ofiK6
8N00mp3buWk9hwwEtXCXlZlQJ1DomtqmaOe5W/AsvxNTKiCoEpHPRoFDzePenykTfX
sKD9BpdPq4efU7ex+BulAalSDWvxi776HiH0Du4JiXz8GvVr+JQd9NhNElDL/j+zdF
GCzdc4WdWlbhzb/nlCi+6s2u4g6wIDAQABAoIBACUl3Wuo4tRWG1jhqv+yGVQZDn4j
njPH5PdFaKd3Rg5DZUQeZZ9rrNNDaS6pa/OWngPairtjF+rRRwIJ1ZhKMpP//71RVt
Ar9Eu0jUBvYkWoFVFTlAu1aJP8iDTiX7DQ1N/iQRdnNrjfld0IEXY6NMU30GRQ5nLJ
H/Xfb2NP+SwpWD5pzK1rnHtYUMhtKs8SzMhUax7UI5UUGIcuRjEbjR3F0gA87YtZee
/zVdIRhuklGcWghc01AFLgENnLNEngykmdQjAn4lAX5eM+/nGPHxUfbWIihLNW+uTV
31g4mFCxCkTsipyxC22xTZTWFlq806jkn/s3xSlYzJ1XGY+gBkECgYEA+FlPDTzKQz
OdWv11PiCYXdtnDLyW3dfAsyvSj4SOlmgqqfVbrkjtwvelwBJQFP2xcD681rstf8Wp
gM9+sCIXkr/r70LB+5kGCSDVpwVm610nrMav3nkQpzeutJICFgOBbN/0cDL94/9ff/
sGDSNSPERJMJYd9jlOQaKF65x3wu8CgYEA5CR1sCGeHKqBf26L67u0Kt7EuEd+DV3a
l0D/7EGD+c+p7m/o8RGVEwZRWzv6IdZfA3/9P/oDcO+qjWMuQrhxHmx035pQU1K+tX
+G
-----END RSA PRIVATE KEY-----
I am using this template to create the object
CK_ATTRIBUTE privateKeyTemplate[] =
{
{ CKA_CLASS, &classPrivateKey, sizeof(classPrivateKey) },
{ CKA_LABEL, labelPrivate, strlen((char*)labelPrivate) },
{ CKA_KEY_TYPE, &keyType, sizeof(keyType) },
{ CKA_TOKEN, &bTrue, sizeof(bTrue) },
{ CKA_ID, enrollmentId, sizeof(enrollmentId) },
{ CKA_PRIVATE, &bTrue, sizeof(bTrue) },
{ CKA_VALUE, byteArray, sizeof(byteArray) },
{ CKA_VALUE_LEN, &l, sizeof(l) },
{ CKA_SUBJECT, enrollmentId, sizeof(enrollmentId) },
{ CKA_MODULUS, modulusArray, modulusArrayLength },
{ CKA_PRIVATE_EXPONENT, privateExponentArray, privateExponentArrayLength},
{ CKA_PUBLIC_EXPONENT, exponentArray, exponentArrayLength },
{ CKA_EXPONENT_1, exp1Array, exp1ArrayLength },
{ CKA_EXPONENT_2, exp2Array, exp2ArrayLength },
{ CKA_PRIME_1, pArray, pArrayLength },
{ CKA_PRIME_2, qArray, qArrayLength },
{ CKA_COEFFICIENT, qInvArray, qInvArrayLength },
{ CKA_DERIVE, &bFalse, sizeof(bFalse) },
{ CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
{ CKA_DECRYPT, &bTrue, sizeof(bTrue) },
{ CKA_SIGN, &bTrue, sizeof(bTrue) },
{ CKA_SIGN_RECOVER, &bFalse, sizeof(bFalse) },
{ CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) },
{ CKA_MODIFIABLE, &bFalse, sizeof(bFalse) },
{ CKA_WRAP, &bTrue, sizeof(bTrue) }
};
Here is my full function:
void Dongle::createPrivateKey(char *data, char* enrollmentId, CK_SESSION_HANDLE hSession) {
CK_RV rv = CKR_OK;
CK_BBOOL bFalse = CK_FALSE;
CK_BBOOL bTrue = CK_TRUE;
CK_KEY_TYPE keyType = CKK_RSA;
CK_OBJECT_HANDLE hObject;
std::string labelPriv = std::string("private") + enrollmentId;
CK_UTF8CHAR * labelPrivate = convertToCK_UTF8CHAR(labelPriv); //Label of private key.
RSA* rsa_key = NULL;
d::decode_rsa_private_key(data, &rsa_key);
std::string s = std::string(data);
d::removeSubstrs(s, "\n");
d::removeSubstrs(s, "-----BEGIN RSA PRIVATE KEY-----");
d::removeSubstrs(s, "-----END RSA PRIVATE KEY-----");
int l;
CK_BYTE * byteArray = d::base64_decode(s.c_str(), &l);
for (int i=0; i<l; i++) {
printf("%x ", byteArray[i]);
}
if (rsa_key != NULL) {
// Access modulus and exponent
const BIGNUM* modulus = RSA_get0_n(rsa_key);
unsigned char* modulusArray = NULL;
size_t modulusArrayLength;
d::bignum_to_bytearray(modulus, &modulusArray, &modulusArrayLength);
const BIGNUM* exponent = RSA_get0_e(rsa_key);
unsigned char* exponentArray = NULL;
size_t exponentArrayLength;
d::bignum_to_bytearray(exponent, &exponentArray, &exponentArrayLength);
const BIGNUM* privateExponent = RSA_get0_d(rsa_key);
unsigned char* privateExponentArray = NULL;
size_t privateExponentArrayLength;
d::bignum_to_bytearray(privateExponent, &privateExponentArray, &privateExponentArrayLength);
const BIGNUM* p = RSA_get0_p(rsa_key);
unsigned char* pArray = NULL;
size_t pArrayLength;
d::bignum_to_bytearray(p, &pArray, &pArrayLength);
const BIGNUM* q = RSA_get0_q(rsa_key);
unsigned char* qArray = NULL;
size_t qArrayLength;
d::bignum_to_bytearray(q, &qArray, &qArrayLength);
const BIGNUM* exp1 = RSA_get0_dmp1(rsa_key);
unsigned char* exp1Array = NULL;
size_t exp1ArrayLength;
d::bignum_to_bytearray(exp1, &exp1Array, &exp1ArrayLength);
const BIGNUM* exp2 = RSA_get0_dmq1(rsa_key);
unsigned char* exp2Array = NULL;
size_t exp2ArrayLength;
d::bignum_to_bytearray(exp2, &exp2Array, &exp2ArrayLength);
const BIGNUM* qInv = RSA_get0_iqmp(rsa_key);
unsigned char* qInvArray = NULL;
size_t qInvArrayLength;
d::bignum_to_bytearray(qInv, &qInvArray, &qInvArrayLength);
CK_OBJECT_CLASS classPrivateKey = CKO_PRIVATE_KEY;
CK_ATTRIBUTE privateKeyTemplate[] =
{
{ CKA_CLASS, &classPrivateKey, sizeof(classPrivateKey) },
{ CKA_LABEL, labelPrivate, strlen((char*)labelPrivate) },
{ CKA_KEY_TYPE, &keyType, sizeof(keyType) },
{ CKA_TOKEN, &bTrue, sizeof(bTrue) },
{ CKA_ID, enrollmentId, sizeof(enrollmentId) },
{ CKA_PRIVATE, &bTrue, sizeof(bTrue) },
{ CKA_VALUE, byteArray, sizeof(byteArray) },
{ CKA_VALUE_LEN, &l, sizeof(l) },
{ CKA_SUBJECT, enrollmentId, sizeof(enrollmentId) },
{ CKA_MODULUS, modulusArray, modulusArrayLength },
{ CKA_PRIVATE_EXPONENT, privateExponentArray, privateExponentArrayLength},
{ CKA_PUBLIC_EXPONENT, exponentArray, exponentArrayLength },
{ CKA_EXPONENT_1, exp1Array, exp1ArrayLength },
{ CKA_EXPONENT_2, exp2Array, exp2ArrayLength },
{ CKA_PRIME_1, pArray, pArrayLength },
{ CKA_PRIME_2, qArray, qArrayLength },
{ CKA_COEFFICIENT, qInvArray, qInvArrayLength },
{ CKA_DERIVE, &bFalse, sizeof(bFalse) },
{ CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
{ CKA_DECRYPT, &bTrue, sizeof(bTrue) },
{ CKA_SIGN, &bTrue, sizeof(bTrue) },
{ CKA_SIGN_RECOVER, &bFalse, sizeof(bFalse) },
{ CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) },
{ CKA_MODIFIABLE, &bFalse, sizeof(bFalse) },
{ CKA_WRAP, &bTrue, sizeof(bTrue) }
};
// Clean up
delete[] byteArray;
rv = C_CreateObject( hSession,
privateKeyTemplate,
1,
&hObject );
if (rv == CKR_OK) {
std::cout<< "Created object handle"<< hObject<< std::endl;
}
// Clean up
RSA_free(rsa_key);
}
}
I am getting CKR_TEMPLATE_INCOMPLETE
when trying to create the object.
The third argument to C_CreateObject should be the number of attributes in the template -- for your current code 25, not 1. But better coding practice is to compute it, so you don't forget to update it when you change something: sizeof(privateKeyTemplate)/sizeof(privateKeyTemplate[0])
or sizeof(privateKeyTemplate)/sizeof(CK_ATTRIBUTE)
(whichever you prefer).
Also, you are using only the first 4 or 8 characters pointed to by enrollmentId
for CKA_ID, and trying to do the same for CKA_SUBJECT which must be a DER encoding not a character string. Similarly you are pointing to only part of byteArray
for CKA_VALUE, or would be if you hadn't deleted it prematurely which means there may not be anything there and it may even crash (although that's rare for something this small). Plus I don't recall seeing any device use CKA_VALUE for a privatekey object at all, but my experience doesn't include SafeNet.