I am using SoftHSM and I have to develop a Java application to extract objects of it.
I have a "Data" object of label "MY_DATA" and I have successfully opened the session on the right token.
But even if there is no error returned code, I cannot get anything: objectHandles
is always empty (and ulObjectCount
= 0).
Note that I get a list of handles when I use a null template. Thus, I think the issue is around the definition of the template (types used...) But what?
I am trying to get my Object with the following Java/JNA code (my JNA interface is called Pkcs11Library).
String dataLabel = "MY_DATA";
CK_ATTRIBUTE[] searchTemplate = (CK_ATTRIBUTE[]) new CK_ATTRIBUTE().toArray(2);
searchTemplate[0].type = new NativeLong(Pkcs11Library.CKA_LABEL); // long CKA_LABEL = 0x00000003
byte[] labelBytes = dataLabel.getBytes();
searchTemplate[0].pValue = new Memory(labelBytes.length);
searchTemplate[0].pValue.write(0, labelBytes, 0, labelBytes.length);
searchTemplate[0].ulValueLen = new NativeLong(labelBytes.length);
searchTemplate[1].type = new NativeLong(Pkcs11Library.CKA_CLASS); // long CKA_CLASS = 0x00000000
searchTemplate[1].pValue = new Memory(NativeLong.SIZE);
searchTemplate[1].pValue.setNativeLong(0, new NativeLong(Pkcs11Library.CKO_DATA)); // long CKO_DATA = 0x00000000
searchTemplate[1].ulValueLen = new NativeLong(NativeLong.SIZE);
int rv = Pkcs11Library.INSTANCE.C_FindObjectsInit(hSession, searchTemplate, searchTemplate.length);
if (rv != Pkcs11Library.CKR_OK) {
//TODO
}
int[] objectHandles = new int[MAX_OBJECT_COUNT]; // MAX_OBJECT_COUNT = 10
NativeLongByReference pulObjectCount = new NativeLongByReference();
rv = Pkcs11Library.INSTANCE.C_FindObjects(hSession, objectHandles, objectHandles.length, pulObjectCount);
int ulObjectCount = pulObjectCount.getValue().intValue();
My JNA interface is defined as follows:
// CK_ATTRIBUTE
public class CK_ATTRIBUTE extends Structure {
public NativeLong type;
public Pointer pValue;
public NativeLong ulValueLen;
public CK_ATTRIBUTE() {
super();
}
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("type", "pValue", "ulValueLen");
}
}
int C_FindObjectsInit(int hSession, CK_ATTRIBUTE[] searchTemplate, int length);
int C_FindObjects(int hSession, int[] phObject, int ulMaxObjectCount, NativeLongByReference pulObjectCount);
The native definitions are defined here:
struct ck_attribute
{
ck_attribute_type_t type;
void *value;
unsigned long value_len;
};
CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount);
I am on Windows x64 with OpenJDK17 and I use the x64 dll of SoftHSMv2.
Your problem is likely Data Structure Alignment. Third party libraries often don't use any alignment of bytes in structures.
Since your comments indicated you are on Windows, the various types that all map to
unsigned long
are 4 bytes each, soint
is appropriate here. (I might suggest you be consistent in always using eitherint
orNativeLong
, it is confusing when you use both.)However, pointer size is 8 bytes, so your structure byte width looks like:
On Windows, JNA Structures use the default alignment to field width. After assigning the first 4 bytes for
type
, it must assign the 8-byte value forpValue
, but that must be 8-byte aligned. The variable can't cross that byte boundary so therefore JNA is sending this structure:To resolve this, use the
setAlignType()
method usingALIGN_NONE
which doesn't use padding: