Hi,
as part of a thesis, I’m looking into whether it’s possible to use USB or smartcard tokens for database encryption instead of a larger HSM. Considering the mutual PKCS#11 interface I expected this to be quite feasible and bought a NitroKey HSM 2. However, it has since become clear that the provided interfaces don’t fully implement PKCS#11, and therefore won’t work out of the box.
I’ve decided to build onto https://github.com/CardContact/sc-hsm-embedded/tree/aes as it seems to provide most of the requirements, including AES key generation, encryption, and decryption. Still, it lacks the ability to create and manage data objects. I’ve attempted to implement this feature in sc_hsm_C_CreateObject, but this is difficult with my limited knowledge of the token’s inner workings. So far, I’ve only succeeded in creating what appear to be a session objects despite CKA_TOKEN being set to true. I hope that with correct driver code, it will be possible to store data objects on the token.
It seems like the problem lies in the following code segment and that either the generated FID is not accepted or writeEF expects the data to be encoded in a particular way or written somewhere else.
fid = determineFreeKeyId(slot, DATA_PREFIX);
if (fid < 0)
FUNC_FAILS(CKR_DEVICE_ERROR, "Determine free id failed");
fid = (DATA_PREFIX << 8) | (fid & 0xFF);
rc = writeEF(slot, fid, val, vallen);
For reference, this is the entire function pertaining to data objects:
static int sc_hsm_C_CreateObject(
struct p11Slot_t* slot,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount,
struct p11Object_t** pp11o)
{
int pos, rc, vallen, idlen;
unsigned short fid, certfid;
CK_CERTIFICATE_TYPE ct;
CK_ATTRIBUTE idattr = { CKA_ID, NULL, 0 };
CK_OBJECT_CLASS objclass;
unsigned char* val, * po, * id;
struct p11Object_t* p11Key, * p11o;
struct p15CertificateDescription* p15cert;
unsigned char buff[512];
struct bytebuffer_s bb = { buff, 0, sizeof(buff) };
pos = findAttributeInTemplate(CKA_CLASS, pTemplate, ulCount);
if (pos == -1)
FUNC_FAILS(CKR_TEMPLATE_INCOMPLETE, "CKA_CLASS not found in template");
rc = validateAttribute(&pTemplate[pos], sizeof(CK_OBJECT_CLASS));
if (rc != CKR_OK)
FUNC_FAILS(rc, "CKA_CLASS");
objclass = *(CK_OBJECT_CLASS*)pTemplate[pos].pValue;
if ((objclass != CKO_CERTIFICATE) && (objclass != CKO_DATA))
FUNC_FAILS(CKR_TEMPLATE_INCONSISTENT, "CKA_CLASS must be CKO_CERTIFICATE or CKO_DATA");
pos = findAttributeInTemplate(CKA_VALUE, pTemplate, ulCount);
if (pos == -1)
FUNC_FAILS(CKR_TEMPLATE_INCOMPLETE, "CKA_VALUE not found in template");
rc = validateAttribute(&pTemplate[pos], 0);
if (rc != CKR_OK)
FUNC_FAILS(rc, "CKA_VALUE");
val = (unsigned char*)pTemplate[pos].pValue;
vallen = pTemplate[pos].ulValueLen;
id = NULL;
p11Key = NULL;
p11o = NULL;
idlen = 0;
if (objclass == CKO_CERTIFICATE) {
// Long and not relevant here
}
else if (objclass == CKO_DATA) {
if (p11Key != NULL) {
fid = p11Key->tokenid;
rc = writeEF(slot, (DATA_PREFIX << 8) | p11Key->tokenid, val, vallen);
if (rc < 0)
FUNC_FAILS(CKR_DEVICE_ERROR, "Error writing data object");
}
else {
fid = determineFreeKeyId(slot, DATA_PREFIX);
if (fid < 0)
FUNC_FAILS(CKR_DEVICE_ERROR, "Determine free id failed");
fid = (DATA_PREFIX << 8) | (fid & 0xFF);
rc = writeEF(slot, fid, val, vallen);
if (rc < 0)
FUNC_FAILS(CKR_DEVICE_ERROR, "Error writing data object");
if (p11o != NULL) {
removeTokenObject(slot->token, p11o->handle, TRUE);
}
p11o = calloc(sizeof(struct p11Object_t), 1);
if (p11o == NULL) {
FUNC_FAILS(CKR_HOST_MEMORY, "Out of memory");
}
rc = createDataObject(pTemplate, ulCount, p11o);
if (rc != CKR_OK) {
free(p11o);
FUNC_FAILS(rc, "Could not create data object");
}
p11o->tokenid = (int)fid;
}
}
addObject(slot->token, p11o, TRUE);
*pp11o = p11o;
FUNC_RETURNS(CKR_OK);
}
Perhaps someone more experienced can point me towards the problem and/or relevant resources on developing drivers for the token.