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 04/30/2013 05:58 PM, Michael StJohns wrote:
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.
The idea here is that each C_EncryptUpdate()/DecryptUpdate() call maps to a complete AEAD block. The issue is there is a single Init call, so you can't supply a new IV and AAD without tweaking things. The advantage of this is if you have a stream of AEAD blocks using the same key, certain key schedule and GCM key precalculations can be cached across Update calls. This could be a win in TLS.

On the balance, the new IV/AAD issue is probably a show stopper here.

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.

I'm assuming from your comments that you mean 'both' as in single shot versus multi-shot, not to varying interpretations on what to output in multi-shot (which is what I meant to convey). I'm OK with multi-shot. The 'buffer our decrypt data until you have all of it and return it on C_Finalize' doesn't seem all that useful, but the issue with IV and AAD in the 'each XXXUpdate represents a full GCM block with MAC' makes this one problematic. We implemented just single shot because both interpretations converge to the same thing in the single shot case.


----- 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
This is CVS with 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.

No, because the spec specifically says that no data is returned on final. Each C_EncryptUpdate call is a complete CTS 'block'. That is each call has be be at least on block long and the encrypted output is the same as the encrypted input. The 'stealing' happens on each Update call.

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.
Yes, The spec is correct for what it intended to specify. When I actually implemented this, I actually started implementing what you said, but then I read the input/output spec with the no data on final comment. It became clear CTS was supposed to happen on each update call. This is how CTS is actually used in real life (kerberos sends multiple CTS packets on the same stream with the same key).


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.

Actually, there is. The spec universally uses 'C_Encrypt' to mean both 'C_Encrypt' and 'C_EncryptUpdate'. That's been a long term source of confusion we should probably fix.

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.

Do you mean three mechanism?

I'm definitely OK with that.

bob

Mike







---------------------------------------------------------------------
To unsubscribe from this mail list, you must leave the OASIS TC that generates this mail. Follow this link to all your TCs in OASIS at:
https://www.oasis-open.org/apps/org/workgroup/portal/my_workgroups.php


Attachment: smime.p7s
Description: S/MIME Cryptographic Signature



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