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

 


Help: OASIS Mailing Lists Help | MarkMail Help

pkcs11 message

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


Subject: Re: [pkcs11] C_Encrypt vs C_EncryptUpdate* + C_EncryptFinal. Was: [re]New Mechanisms subgroup Part 1 or 4 new in v2.3



I got a private note that suggested the processing approaches I've been discussing with Robert are subject to interpretation. I disagreed as this is really black letter stuff. Let's first consider AEAD modes of ciphers, where the output is both encrypted data and a "signature" or integrity tag. In the simplest and most correct interpretation, what we're doing is combining a signing operation and an encryption operation into a single set of C_Encrypt* operations.

So first looking at C_EncryptInit

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.
and C_Encrypt
For most mechanisms, C_Encrypt is equivalent to a sequence of C_EncryptUpdate
operations followed by C_EncryptFinal.

And then looking at C_SignInit
After calling C_SignInit, the application can either call C_Sign to sign in a single part; or call C_SignUpdate one or more times, followed by C_SignFinal, to sign data in multiple parts. The signature operation is active until the application uses a call to C_Sign or C_SignFinal to actually obtain the signature. To process additional data (in
single or multiple parts), the application must call C_SignInit again.
and C_Sign
For most mechanisms, C_Sign is equivalent to a sequence of C_SignUpdate operations
followed by C_SignFinal.

You don't get the signature out until you call the final operation either implicitly with C_Sign or explicitly with C_SignFinal. Continuing that thought for AEAD modes, you don't get the AEAD integrity tag out until you call C_Encrypt or C_EncryptFinal.

And in fact CKM_AES_CCM says pretty much exactly that:

Call C_Encrypt(), or C_DecryptUpdate()*§ C_EncryptFinal(), for the plaintext obtaining ciphertext output obtaining the final ciphertext output and the MAC. The total length of data processed must be ulDataLen. The output length will be
ulDataLen + ulMACLen.
[Yes, I just saw the typo in this section - should be C_EncryptUpdate()]

So what do you get for interim calls to C_EncryptUpdate? The mode CKM_AES_CCM as specified is silent on this. You could either output encrypted data for each C_EncryptUpdate or hold all of the data until the C_EncryptFinal and both are probably legitimate choices.


For the Decrypt operation, FIPS requires that you hold the decrypted data until the tag verifies, but I would probably annotate the section to permit in the general case of per section output of decrypted data, but note that if FIPS is in force you should buffer the decrypted data until tag verification.

This appears to be the case for the description of AES-GCM as well.

An alternate way of implementing this may be to use AES_CTR and AES_GMAC with the section 11.13 dual function crypto functions (e.g. C_SignEncryptUpdate). The current PKCS11 spec requires all of the AEAD AAD data to be contiguous and available at the call to C_EncryptInit. That may not actually be the case for a given application.


_________________________________________

Continuing on to CKM_AES_CTS, I'd pretty much start over with the description in the mechanisms document - it's a bit too thin and the no final part is wrong. But I'd look at CKM_AES_CBC_PAD as possibly being the closest match.


The encrypt model for CTS is identical to that for CBC_PAD with the exception of how the padding is supplied and the actual data sent out. In most (all?) of the variations, you can trivially implement CTS as a wrap around to CBC by doing your own padding and post processing steps.

In CKM_AES_CTS the surgery on the last two blocks has to be done as a side effect to C_EncryptFinal (or the implict final of C_Encrypt).

Robert was claiming that each call to C_EncryptUpdate could return a properly padded item (e.g. encrypt 18, 22, and 30 bytes and you get back for each call 18, 22 and 30 bytes with CTS applied). I believe that interpretation to be wrong because of the statement in C_Encrypt:

For most mechanisms, C_Encrypt is equivalent to a sequence of C_EncryptUpdate
operations followed by C_EncryptFinal.

The three calls to CTS implemented in the manner he suggests will not result in the same cipher text as a straight encryption of the total 70 bytes.

On the receiver's side, you would have to know EXACTLY how many bytes the sender put in each chunk to be able to decrypt more than the first block.

I took a look at Kerberos because it was referenced by Robert. Kerberos is doing pretty much plain CTS (it looks like variant 2 of the NIST pub). The only thing interesting is that the IV for message N is the next to last block for message N-1 (which is actually the encrypted final block of message N-1 after CTS post processing). While this looks a lot like a continuous CBC transaction (because the IV for each block is that of the block before), it really isn't. And it only holds for the Kerberos variant of the CTS as far as I can tell.

So Kerberos should do a C_EncryptInit (kerberos-cts, IV), C_Encrypt (plaintext, ciphertext) for message 0, C_EncryptInit (kerberos-cts, ciphertext[next to last block offset]), C_Encrypt (newPlaintext, newCiphertext) for message 0 etc.

Alternately, it can do a C_EncryptInit, C_EncryptUpdate, C_GetOperationState, C_EncryptFinal (to do the padding for message 0), C_SetOperationState, C_EncryptUpdate, C_GetOperationState, C_EncryptFinal for each message afterwards and assuming no stupidity in the implementation, you would get the same thing as above.



Mike












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