This page documents common bugs in PKCS #11 implementations. The items in here could both go into an "Implementers Notes" section of the documentation and should definitely be present in any conformance-test suite.

Length range checks

Implementations use == for range checks instead of >= when checking that buffers are large enough to write data to for C_GetAttributeValue(). This bug is common enough that it's necessary to perform a two-phase read when calling this function, the first to fill in the length and the second to get the actual value:

CK_ATTRIBUTE valueTemplate = { type, NULL_PTR, 0 };

C_GetAttributeValue( hSession, hObject, &valueTemplate, 1 );
valueTemplate.pValue = buffer;
C_GetAttributeValue( hSession, hObject, &valueTemplate, 1 );

C_InitToken() doesn't

C_InitToken() appears to work, but the supposedly-initialised token then fails in various strange and peculiar ways when used. If C_InitToken() can't initialised a token then it should fail, not claim to succeed without actually doing it.

Why is it so hard to initialise a token this way?

C_GetMechanismInfo(), C_GetAttributeValue() return garbage

These functions can leave return values (for C_GetAttributeValue()) or fields (for C_GetMechanismInfo()) un-set or set to garbage while claiming to succeed. To detect this it's necessary to both poison the buffer passed in with known bit-patterns and then check for their presence after the function is called, and to sanity-check all returned data for illegal values, e.g. all-zeroes or all-ones in bitfields.

Lack of enforcement of usage flags

Many implementations seem to pay no attention to usage flags, allowing (for example) a sign-only key to be used for decryption as well.

Reading multiple attributes at once via templates

Implementations treat the ability to read attributes through C_GetAttributeValue() as atomic, so either all succeed or all fail, and if they fail the error information that's returned is typically useless in pinpointing the error. This is so unreliable that most users quickly learn to never try and read more than one attribute at a time.

C_FindObjectsInit/Find/End can't be interrupted

Interrupting the sequence C_FindObjectsInit/C_FindObjects/C_FindObjectsEnd with a different call results in inconsistent/erratic results. This makes it difficult to safely perform any general processing of multiple objects rather than just using the find-objects capability as a basic "find me this one object".

CommonBugs (last edited 2013-03-08 23:49:31 by pgutmann)