PKCS中的内存所有权#11 C_FindObjects其中ulMaxObjectCount!= 1

时间:2015-09-16 06:45:05

标签: cryptography pkcs#11

当API返回可变长度的项目列表时,PKCS#11 v2.40的作者使用了一种通用模式。在诸如C_GetSlotListC_GetMechanismList之类的API中,应用程序需要两次调用API。在第一次调用中,指向CK_ULONG的指针设置为下次调用时将返回的项目数。这允许应用程序分配足够的内存并再次调用API以检索结果。

C_FindObjects调用也返回可变数量的项目,但它使用不同的范例。参数CK_OBJECT_HANDLE_PTR phObject设置为结果列表的头部。参数CK_ULONG_PTR pulObjectCount设置为返回的项目数,确保小于CK_ULONG ulMaxObjectCount

标准没有明确说明phObject必须是指向足以容纳ulMaxObjectCount CK_OBJECT_HANDLE s的内存块的有效指针。

可以将标准解释为应用程序必须悲观地为ulMaxObjectCount个对象分配足够的内存。或者,可以将标准解释为PKCS#11实现将分配pulObjectCount CK_OBJECT_HANDLE,然后应用程序负责释放该内存。然而,后来的解释似乎是可疑的,因为标准中没有其他地方PKCS#11的实现曾经分配内存。

这段话是:

C_FindObjects continues a search for token and session objects that 
match a template, obtaining additional object handles. hSession is 
the session’s handle; phObject points to the location that receives 
the list (array) of additional object handles; ulMaxObjectCount is 
the maximum number of object handles to be returned; pulObjectCount 
points to the location that receives the actual number of object 
handles returned.

If there are no more objects matching the template, then the location 
that pulObjectCount points to receives the value 0.

The search MUST have been initialized with C_FindObjectsInit.

非规范性示例不是很有用,因为它将ulMaxObjectCount设置为1.但是,它确实为该一个条目分配了内存。这似乎表明应用程序必须悲观地预先分配内存。

CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hObject;
CK_ULONG ulObjectCount;
CK_RV rv;
.
.
rv = C_FindObjectsInit(hSession, NULL_PTR, 0);
assert(rv == CKR_OK);
while (1) {
 rv = C_FindObjects(hSession, &hObject, 1, &ulObjectCount);
 if (rv != CKR_OK || ulObjectCount == 0)
 break;
 .
 .
}
rv = C_FindObjectsFinal(hSession);
assert(rv == CKR_OK);

规范链接:http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.pdf

1 个答案:

答案 0 :(得分:7)

是的,应用程序似乎负责为C_FindObjects()返回的对象句柄分配空间。示例代码执行此操作,即使它一次只请求一个对象句柄,您也应如此。

您也可以重写示例代码以请求多个对象句柄,例如像这样:

#define MAX_OBJECT_COUNT 100  /* arbitrary value */

K_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hObjects[MAX_OBJECT_COUNT];
CK_ULONG ulObjectCount, i;
CK_RV rv;

rv = C_FindObjectsInit(hSession, NULL_PTR, 0);
assert(rv == CKR_OK);
while (1) {
  rv = C_FindObjects(hSession, hObjects, MAX_OBJECT_COUNT, &ulObjectCount);
  if (rv != CKR_OK || ulObjectCount == 0) break;
  for (i = 0; i < ulObjectCount; i++) {
    /* do something with hObjects[i] here */
  }
}
rv = C_FindObjectsFinal(hSession);
assert(rv == CKR_OK);

据推测,在单个C_FindObjects()调用中请求多个对象句柄的能力旨在作为性能优化。

FWIW,这几乎就是fread()这样的C标准库函数的功能。使用fgetc()一次一个字节地读取文件中的数据是非常低效的,因此fread()函数允许您分配一个任意大的缓冲区并读取适合它的数据。