OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.


Help: OASIS Mailing Lists Help | MarkMail Help

pkcs11-comment message

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]

Subject: RE: [pkcs11-comment] C_Decrypt / C_DecryptFinal behavior



your set up implies that you intend to call C_Decrypt() multiple times, getting back 2 of the 4000 blocks on each call.. you need to use C_DecryptUpdate() for something like that; C_Decrypt() can only be used to âdecrypt data in a single partâ which means it can only be called once for the actual decryption operation (as the first such call terminates the operation; of course, you can call it provisionally with a NULL output ptr to get the expected output length, but that doesnât perform a decryption and is not going to change the context state)


if you insist on using C_Decrypt() with CKM_AES_CBC_PAD for 4000 blocks, the call that is to perform the decryption must have the output buffer length set to at least AES_BLOCK_LEN * 4000; len will then get set to the actual number of plaintext bytes produced by the operation






From: pkcs11-comment@lists.oasis-open.org <pkcs11-comment@lists.oasis-open.org> On Behalf Of Jason King
Sent: Thursday, June 13, 2019 9:15 PM
To: pkcs11-comment@lists.oasis-open.org
Subject: [pkcs11-comment] C_Decrypt / C_DecryptFinal behavior


In attempting to fix a bug in a PKCS#11 implementation, Iâve come across a somewhat hairy scenario that Iâm hoping someone can provide some guidance:  The base specification section 5.2 describes the behavior when dealing with variable sized buffer arguments:


1.     If pBuf is NULL_PTR, then all that the function does is return (in *pulBufLen) a number of bytes which would suffice to hold the cryptographic output produced from the input to the function.  This number may somewhat exceed the precise number of bytes needed, but should not exceed it by a large amount.  CKR_OK is returned by the function.

2.     If pBuf is not NULL_PTR, then *pulBufLen MUST contain the size in bytes of the buffer pointed to by pBuf.  If that buffer is large enough to hold the cryptographic output produced from the input to the function, then that cryptographic output is placed there, and CKR_OK is returned by the function.  If the buffer is not large enough, then CKR_BUFFER_TOO_SMALL is returned.  In either case, *pulBufLen is set to hold the exact number of bytes needed to hold the cryptographic output produced from the input to the function.


For the definition of C_Decrypt() and C_DecryptFinal(), it also indicates that an error of CKR_BUFFER_TOO_SMALL doesnât terminate the ongoing operation, implying that even with the output buffer in the call isnât NULL, the functions can be called again (without calling C_DecryptInit() again) to retrieve the plaintext.  For most mechanisms, this isnât a problem.  However some mechanisms (such as CKM_AES_CBC_PAD) require decrypted the entire input ciphertext before the actual plaintext size is known, and satisfying the pBuf != NULL and allowing retries when CKR_BUFFER_TOO_SMALL is returned seems problematic to satisfy both behaviors.  For example:


CK_BYTE ciphertext[AES_BLOCK_LEN * 4000] = { â };

CK_BYTE_PTR *plaintext;


CK_MECHANISM mech = { CKM_AES_CBC_PAD, iv, ivlen };


/* Note that plaintext is << ciphertext */

plaintext = malloc(AES_BLOCK_LEN * 2);

len = AES_BLOCK_LEN * 2;


C_DecryptInit(handle, &mech, keyHandle);



 * This should return CKR_BUFFER_TOO_SMALL, however to set len appropriately,

 * the entire contents of ciphertext must be decrypted, and the resulting ciphertext

 * must be saved internally as part of the operation, or the decryption operation state

 * must support some sort of rollback or snapshot to perform the full decryption

 * each time C_Decrypt() is called without the current operation terminating.


C_Decrypt(hSession, ciphertext, sizeof (ciphertext), plaintext, &len);


Iâm not really sure what the best thing to do here â Iâm not aware of any AES-CBC mechanisms that really support any sort of checkpoint/rollback â one could duplicate the current decryption state on each C_Decrypt/C_DecryptUpdate/C_DecryptFinal call until itâs determined the copy is no longer needed, but that seems clunky.  I havenât found anything that seems like it would take precedence over the two behaviors â did I just miss it (I looked at both the 2.40 w/ errata as well as the draft 3.0 and didnât see anything that looked like it might), or would it be worth clarifying the behavior in such a situation?



[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]