> From: owner-openssl-us...@openssl.org On Behalf Of pkumarn
> Sent: Wednesday, 21 March, 2012 02:02

> One more thanks from side for replying to this query.,.. my comments
> inline...
> 
Aside: Usenet convention is response lines, including 'inline' 
ones, have no prefix, and (all) quoted lines do, usually 
(as I have) a greater-than sign. That is unambiguous and 
easier to see at a glance than your embedded <<>> marks.

> 
> So are you saying that their is no way to extract IV and 
> check back if the
> decrypted key matches the encrypted key? I feel this would 
> give space for
> more vulnerabilities as one needs to make sure before using 
> the decryted key
> it is the right key. Or is it like AES_unwrap() will fail on 
> decryption? Not
> clear on this part...  
> 
Yes, there is no way to extract the IV from AES_unwrap_key, 
and it will return 0 if you don't give the correct IV.
As with other IV-based modes, the decryptor MUST provide 
the same IV the encryptor used. In most uses the encryptor 
chooses the IV randomly, and therefore the IV must be 
transmitted or stored along with the ciphertext. But for 
key wrapping like this, assuming your data keys are random 
as they should be, you don't really need nonce IVs, and 
you could have both wrap and unwrap use the default in 
those routines (8 x A6) or some other fixed value.

> 
> Dave Thompson-5 wrote:
> > 
> >> From: owner-openssl-us...@openssl.org On Behalf Of pkumarn
> >> Sent: Monday, 19 March, 2012 09:17
> > 
> >> I have a requirement of wrapping a 512-bit DEK witk 256 bit 
> >> KEK. I picked up
> >> openssl API and figured out that it provides AES_wrap_key() 
> >> to do the job. I
> > 
> > OpenSSL's AES_{wrap,unwrap}_key does *a* key wrapping, 
> > but not the only possible one. You need to make sure the 
> > unwrap matches it (easy if you do the unwrap yourself). 
> > 
> >> wrote a small program (snippet below) to get the job done but 
> >> when i check
> >> out the values in "dek", i see all values as zero. Not 
> sure what i am
> >> missing?
> >> 
> > See below.
> > 
> >> Also is their anyway i can extract the "IV" when i do the 
> >> reverse of above
> >> logic using AES_unwrap_key()?
> >> 
> > No, as with other chain modes you must transmit the IV used 
> > at encrypt to decrypt -- unless you always make it the same 
> > which should be okay here, since the wrappee (data) keys 
> > should be unique so duplicate IV (+key) doesn't risk 
> > identifying repeats as it would for more generic data.
> > Although internally it is used differently; instead of 
> > chaining forward in both encrypt and decrypt, this decrypt 
> > (unwrap) chains backward and then verifies the IV;
> > if it extracted the IV instead it would probably be 
> > vulnerable to some tampering attacks.
> > 
> > <<>> : In my case, i would be storing the wrapped key and 
> not the original
> > key. So when user tries to decrypt the wrapped key, he would get the
> > original key but how do i make sure that is the right key. So the
> > suggestion is to see if i can get the same IV i have used 
> to encrypt which
> > indirectly proves that the key decrypted is the right one.
> > 

Even if you could recover the IV instead of supplying it, 
as this wrap algorithm *could* do (unlike normal CBC etc.),
it doesn't prove the unwrapped=decrypted key is correct. 
CBC modes are often vulnerable to blockwise attacks 
(although I haven't worked out this one specifically).
In general most encryption schemes don't attempt to provide 
integrity protection and shouldn't be relied on for that;
even the common practice of checking PKCS#5 padding (for 
varying data in a block mode) is weak and many cryptosystems 
that relied on 'if it decrypts sensibly it must be correct' 
have been broken precisely that way. This is even more true 
where the encrypted data is a key which is just bits.

If you want a check on the key unwrap (and usually people 
do, because of the impact if it is wrong), do a check.
One common technique is for the wrapper to (separately) 
use the original key to encrypt a known block, such as 
all 0 or "KEY CHECK VALUE", and transmit/store that value 
along with the wrapped key, or a portion of it like the 
first 4 bytes or so. The unwrapper uses the recovered key 
to do the same encryption and compares. More generic 
methods are to add an MDC (a hash) to the original key 
before wrapping, or a MAC (such as a keyed hash) after;
but for the latter you now need to share (and manage) 
the MAC key as well as the wrap=encryption key. 

In the last few years special modes have been developed which 
do provide both encryption and integrity (or authentication). 
TLSv1.2 defines some ciphersuites using Galois Counter Mode 
(GCM) which are apparently implemented in brand-new 1.0.1.
 
> >> #define KEY_LEN     32
> >> u8 dek[KEY_LEN + 8];
> >> static const unsigned char default_iv[] = {
> >>     0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
> >>     };
> >> 
> > for(n = 0; n < KEY_LEN; n++)
> >> actx.rd_key[n] = kek[n];
> >> 
> > I assume actx is an AES_KEY (struct aes_key_st) since you 
> > pass it to AES_wrap_key below. This is NOT how you initialize 
> > an AES_KEY structure; in fact, in general you should never 
> > directly write elements in any OpenSSL-defined structure, 
> > and usually you should avoid reading them where OpenSSL 
> > provides getters (although it doesn't do that everywhere).
> > Use AES_set_encrypt_key (and _decrypt_ for unwrap).
> > 
> > <<>>: Yes "actx" is of type struct aes_key_st. I did come across
> > AES_set_encrypt_key() which did set the data structure of actx but i
> > thought i can also do it directly. Would it give unexpected 
> result, if i
> > set them directly? 
> > 
If you set them all to exactly the same round key values (and count) 
OpenSSL itself computes, which are based on the standard and not at all 
the same as the base key value, in the correct endianness, it will work. 
But if a future version of OpenSSL decides to change the implementation 
because a better technique is found, it will break horribly. Why make 
more work and risk for yourself? Use the API. That's why it exists.

> >> /* Here KEK is got as a function parameter
> >>  Byte contains DEK key
> >>  I am able to successfully print KEK and DEK values and they 
> >> are as expected
> >> */
> >> 
> >> ret = AES_wrap_key(&actx, default_iv, dek, byte, KEY_LEN - 1);
> >> for(n = 0; n < (KEY_LEN + 8); n++)
> >>    printf(" %02x", dek[n]); // this prints all zeros
> >> 
> > Check ret before printing or otherwise using dek[]. It can 
> > and here did indicate an error, and the output buffer isn't set. 
> > Although on checking I see these routines don't fill in 
> > the error queue like most (other) OpenSSL routines.
> > 
> > KEY_LEN-1 is 31 bytes. You can't wrap a 31-byte value; 
> > as I said before it must be a multiple of 8 bytes.
> > You say your requirement is 512 bits; that's 64 bytes 
> > (not 32 as your code #define's and allocates).
> > <<>>: My typo in this...as the above code is just a 
> snippet, i have missed
> > few things here... 
> > 
> > (And as before a 512-bit key if used for a symmetric 
> > algorithm usually indicates uninformed design, but 
> > I assume that's not your responsibility.)
> > 

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to