2015-09-16 20 views
7

Gli autori di PKCS # 11 v2.40 utilizzano uno schema comune quando un'API restituisce un elenco di articoli di lunghezza variabile. Nelle API come C_GetSlotList e C_GetMechanismList, l'applicazione dovrebbe chiamare le API due volte. Nella prima chiamata, un puntatore a CK_ULONG viene impostato sul numero di elementi che verranno restituiti al prossimo richiamo. Ciò consente all'applicazione di allocare memoria sufficiente e di richiamare nuovamente l'API per recuperare i risultati.Proprietà memoria in PKCS # 11 C_FindObjects where ulMaxObjectCount! = 1

La chiamata C_FindObjects restituisce anche un numero variabile di elementi, ma utilizza un paradigma diverso. Il parametro CK_OBJECT_HANDLE_PTR phObject è impostato in testa all'elenco dei risultati. Il parametro CK_ULONG_PTR pulObjectCount è impostato sul numero di elementi restituiti, il che è garantito essere inferiore a CK_ULONG ulMaxObjectCount.

Lo standard non dice esplicitamente che phObject deve essere un puntatore valido per un blocco di memoria abbastanza grande da contenere ulMaxObjectCountCK_OBJECT_HANDLE s.

Uno potrebbe interpretare lo standard nel senso che l'applicazione deve allocare pessimisticamente memoria sufficiente per gli oggetti ulMaxObjectCount. In alternativa, è possibile interpretare lo standard nel senso che l'implementazione PKCS # 11 assegnerà pulObjectCountCK_OBJECT_HANDLE s ed è quindi responsabilità dell'applicazione liberare tale memoria. Questa interpretazione successiva sembra tuttavia sospetta, poiché in nessun altro punto dello standard l'implementazione di PKCS # 11 assegna mai memoria.

Il passaggio è:

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. 

L'esempio non normativa non è molto utile, in quanto imposta ulMaxObjectCount a 1. Esso, tuttavia, allocare la memoria per quella voce. Il che sembra indicare che l'applicazione deve pre-allocare pessimisticamente la memoria.

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); 

Specification Link: http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.pdf

+0

Sono d'accordo, è borderline. Sebbene sia probabile che qualcuno su S.O. ha un'idea di come la memoria è generalmente gestita, è quasi certo che qualcuno qui abbia usato la libreria C PKCS # 11 in modo specifico. – Huckle

risposta

6

Sì, sembrerebbe che l'applicazione è responsabile per l'assegnazione dello spazio per l'oggetto restituito da maniglie C_FindObjects(). Il codice di esempio lo fa, anche se richiede solo un singolo handle di oggetto alla volta, e così dovresti.

Si potrebbe anche riscrivere il codice di esempio per richiedere più handle di oggetto, ad es. in questo modo:

#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); 

Presumibilmente, la possibilità di richiedere multiplo oggetto gestisce in un unico C_FindObjects() chiamata è intesa come ottimizzazione delle prestazioni.

FWIW, questo è esattamente il numero esatto di funzioni di libreria standard C come fread(). Sarebbe estremamente inefficiente leggere i dati da un file un byte alla volta con fgetc(), quindi la funzione fread() consente di allocare un buffer arbitrariamente grande e di leggere tutti i dati che vi si adattano.

+0

Grazie, volevo solo verificare. Immagino che la differenza tra C_GetSlotList e C_FindObjects sia che la libreria probabilmente conosce in anticipo esattamente quanti slot esistono, ma potrebbe non conoscere il numero di oggetti corrispondenti? – Huckle

+1

Questa potrebbe essere una delle ragioni per i diversi stili di API. Potrebbe anche succedere che a C_FindObjects vengano talvolta restituiti molti più risultati C_GetSlotList, in modo che l'allocazione di un singolo buffer per conservarli tutti potrebbe non essere fattibile. Oppure potrebbero esserci problemi di implementazione interna che renderebbero impraticabile riprendere una query parziale di C_GetSlotList. Oppure le diverse parti dell'API potrebbero essere state progettate da persone diverse con preferenze di progettazione API diverse. –

+0

(Personalmente, trovo che lo stile dell'API C_GetSlotList sia piuttosto inelegante, e spesso inefficiente e piuttosto fastidioso da usare - specialmente dato che, come indicato a pagina 73, non è garantito che la dimensione restituita alla prima chiamata * sia effettivamente sufficiente * per i risultati della seconda chiamata, dal momento che il numero di risultati potrebbe essere cambiato nel frattempo.A data una scelta, preferirei molto un'API di stile C_FindObjects, anche se questo significa dover impostare e liberare un oggetto di sessione separato.) –