pkcs11 — archive
[Date Prev]
| [Thread Prev]
| [Thread Next]
| [Date Next]
— [Date Index]
| [Thread Index]
| [Month Index]
| [List Home]
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]
| [Month Index]
| [List Home]