Using the Windows CNG API, I am able to encrypt and decrypt individual blocks of data with authentication, using AES in GCM mode. I now want to encrypt and decrypt multiple buffers in a row.
According to documentation for CNG, the following scenario is supported:
If the input to encryption or decryption is scattered across multiple buffers, then you must chain calls to the BCryptEncrypt and BCryptDecrypt functions. Chaining is indicated by setting the BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG flag in the dwFlags member.
If I understand it correctly, this means that I can invoke BCryptEncrypt
sequentially on multiple buffers an obtain the authentication tag for the combined buffers at the end. Similarly, I can invoke BCryptDecrypt
sequentially on multiple buffers while deferring the actual authentication check until the end. I can not get that to work though, it looks like the value for dwFlags
is ignored. Whenever I use BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG
, I get a return value of 0xc000a002
, which is equal to STATUS_AUTH_TAG_MISMATCH
as defined in ntstatus.h
.
Even though the parameter pbIV
is marked as in/out, the elements pointed to by the parameter pbIV
do not get modified by BCryptEncrypt()
. Is that expected? I also looked at the field pbNonce
in the BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
structure, pointed to by the pPaddingInfo
pointer, but that one does not get modified either. I also tried "manually" advancing the IV, modifying the contents myself according to the counter scheme, but that did not help either.
What is the right procedure to chain the BCryptEncrypt
and/or BCryptDecrypt
functions successfully?
I managed to get it to work. It seems that the problem is in MSDN, it should mention setting
BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG
instead ofBCRYPT_AUTH_MODE_IN_PROGRESS_FLAG
.