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] New Mechanisms subgroup Part 1 or 4 new in v2.3


On 4/30/2013 5:18 PM, Robert Relyea wrote:





----- GCM ---
NIST requires that no data be returned from decrypt until the gmac has been verified. This means there is a little ambiguity as to whether C_EncryptUpdate() should return a fully mac'ed data, or whether the mac should be generated in C_Encrypt final.

Do it in C_EncryptFinal - it's the usual place and doesn't disagree with the NIST guidance.


In the decrypt case, if the mac is included in the C_DecryptUpdate(), it can meet the NIST requirement, but if the MAC is only sent at the end, then the full decrypt data would not be available until C_DecryptFinal().

AEAD fits the C_EncryptUpdate/C_DecrypteUpdate having a fully mac'ed value. Because of the abmiguity, Red Hat disabled C_EncryptUpdate/C_DecryptUpdate, but instead we only implemented GCM as a single-shot encryption (a.la. RSA):

C_EncryptInit()
C_Encrypt()

and.

C_DecryptInit()
C_Decrypt()

There's no requirement to do an output as part of C_DecryptUpdate - it's just the way things normally work.

*sigh* GCM really is a mess with respect to this problem. What I would do is allow C_DecryptUpdate, but do the buffering internally if you're in FIPS mode - it's going to be the same amount of space as the single part operation. The implementation will have to specify an amount of data it can handle.


In repeated calls. This removed the worry about what the meaning of the output for the second C_DecryptUpdate() was (no new AAD, use the same AAD?) and how the internal IV changes.
I don't quite understand this. The IV gets set when you do the init. You update the counter for each block and form a new counter block - but that's pretty straight forward. You encrypt that block to get the value you XOR with the cipher text - that's per block processing, and that state happens internal to the module.

Similiar argument for C_EncryptInit/C_Encrypt/C_EncryptUpdate. It probably makes sense to do the conservative thing in the spec as well.
I don't quite understand this either. There appears to be no bar in the standard to encrypting and outputting the cipher text prior to outputting the tag. You may have to buffer a partial block, but that's typical.


Oracle implemented the meaning that from C_EncryptInit() to C_EncryptFinal() is a single GCM operation with the MAC returned in final. On Decrypt, C_DecryptUpdate() returns no data and buffers it. C_DecryptFinal() returns the entire decryption.

If the PKCS #11 group wants to allow C_EncryptUpdate/C_DecryptUpdate, then we need to decide which semantic we want and make it explicit in the spec.

I think both are legitimate implementations. I sent a note off to Russ Housley (who designed CCM) and pointed out that both modes were designed for packet use. That suggests that the one-shot model may be most correct. But we may still want to spec this for both modes and allow non-FIPS to use the Update functions.


----- CCM ---
We did not implement CCM. It would have the same issues. Longer term we may want a new function for IETF AEAD type functions ( see rfc 5166).
In general, this is more about how much data can be/needs to be buffered inside the PKCS11 module than almost anything else. I think the restriction imposed by NIST for this is extreme, especially since the same key can be used with AES-ECB and a set of fabricated counter blocks to do the decryption, even if the CBC-MAC fails.

------ CTR ---
There were no issues with CTR, the spec is pretty straighforward.

------ CTS ---
Just for my ref - this is CBC with Cipher Text Stealing. Your other message on XTS is XEX based cipher text stealing
A few things. First: though it wasn't clear, the only thing that makes sense for the spec is that each C_EncryptUpate call returns CTS data.
If you initially pass in less than or equal to a full block, then you get no output. If you pass in a single block at a time, you will always be one block behind. You have to be past (not at) a block boundary to get output.

That means that each C_EncryptUpdate/C_DecryptUpdate call must have a length > blocksize length. The spec does say that, but in a way that many interpret to mean only C_Encrypt/C_Decrypt (which conflicts with the explicit statement aht C_Finalize doesn't return anything).
You mean C_EncryptFinal? The statement that there is no final part is actually wrong. You can't calculate the last partial partial block unless you know that you're at the end of the data. If you were processing an exact multiple of the block size the output is going to be the last block.

You need to buffer up to a block at a time internally. There is no requirement that length>blocksize for each call to C_*Update.


Second, we should be clear what the next IV is when multiple C_EncryptUpdate calls are made. We can alieviate both problems the same way we handled GCM (making it single shot), though in this case we didn't implement a single-shot only approach. Oracle would be OK with the single shot approach.
No. the IV is provided as input at init, but the IV for the following blocks is the cipher text of the previous block. The IV is updated internally upon encryption of each block.

There is no requirement this be a single shot, but the "no final part" comment needs to be corrected.


The other issue is an issue with the definition of CTS. The spec simply references NIST SP 800-38A. Unfortunately this spec actually defines 3 different CTS formats:

Type 1, or NIST.
Type 2, or Schneier.
Type 3, or Kerberos.

Spec three modes. Or spec a single mode with a parameter structure which says which of these is in use.

Mike








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