klook
klook

Reputation: 41

pkcs11 - questions regarding `C_EncryptUpdate/C_EncryptFinal`

I'm using C_EncryptUpdate/C_EncryptFinal and I don't really understand what is supposed to do C_EncryptFinal.

My assumption is that C_EncryptFinal is used to add the padding and last block encryption when the size of the buffer to encrypt is not a multiple of the block size.

Am I correct? Shall C_EncryptFinal always be called after a C_EncryptUpdate loop ?

Upvotes: 2

Views: 988

Answers (1)

vlp
vlp

Reputation: 8116

If you want to be sure you have all the ciphertext you should call C_EncryptFinal.

After calling C_EncryptInit, the application can either call C_Encrypt
to encrypt data in a single part; or call C_EncryptUpdate zero or
more times, followed by C_EncryptFinal, to encrypt data in multiple
parts. The encryption operation is active until the application uses
a call to C_Encrypt or C_EncryptFinal to actually obtain the final
piece of ciphertext. To process additional data (in single or
multiple parts), the application must call C_EncryptInit again.

You can replace calls to C_EncryptUpdate and C_EncryptFinal (aka multiple-part operation) with single C_Encrypt if you have all your plaintext ready in a single buffer (aka single-part operation).

(Beware that some mechanisms might support only single-part operation, e.g. CKM_RSA_X_509)


EDIT:

The C_EncryptFinal does not necessarily need to return any data (i.e. the returned encrypted data part length in pulEncryptedPartLen can be zero).

As you say, the CKM_AES_CBC encryption which was fed with block aligned data (via C_EncryptUpdate) will probably return no encrypted data part after C_EncryptFinal for most of the implementations (as they would return the corresponding ciphertext immediately in the C_EncryptUpdate).

But there might exist an implementation, which internally buffers this block aligned data without encrypting it (thus returning zero length output data part in C_EncryptUpdate) and which then encrypts all the buffered data at once during the C_EncryptFinal -- an example might be an implementation backed by a smart card (or a remote host), where it might be a good idea to send data in larger chunks (even if the cryptoki itself receives data in a block sized chunks).

PKCS#11 API allows that and you have to handle it correctly (i.e. check returned lengths, shift your destination pointers/update the space available accordingly).


Think of it as of a universal API which needs to support any imaginable mechanism.

Upvotes: 2

Related Questions