> From: owner-openssl-us...@openssl.org On Behalf Of pkumarn
> Sent: Monday, 19 March, 2012 03:06

> I am trying to use PKCS5_PBKDF2_HMAC_SHA1() and below is my 
> sample program.
> I wanted to make sure if my result of 
> PKCS5_PBKDF2_HMAC_SHA1() is correct so
> i verified the same with the below wesbite 
> http://anandam.name/pbkdf2/ and i
> see a different result... Am i using the API correctly?
> I am having doubts if i am passing salt value correctly...
> 
That site is Javascript which treats the salt (and password) 
directly as data. I don't know if or how browser(s) can 
reliably enter data other than printable ASCII in a <form>; 
it may very well depend on browser and locale settings.
For simplicity if you want to interoperate with this PBKDF2 
implementation I would therefore limit both salt and password 
to printable ASCII 0x20-0x7E. (32 chars of salt, even restricted 
to 5 or 6 bits entropy each, is far more than needed, especially 
if you are deriving a 40-bit key as your code indicates.)

> #include <stdio.h>
> #include <openssl/rand.h>
> #include <types.h>
> #include <string.h>
> #include <stdio.h>
> #include <string.h>
> #include <stdlib.h>
> 
> #include <malloc.h>
> 
> #include <openssl/hmac.h>
> #include <openssl/evp.h>
> #include <openssl/engine.h>
> #include <openssl/aes.h>
> 
Asides: malloc.h is not standard or portable; standardly 
malloc() and related functions are in stdlib.h.
types.h is not standard C (though sys/types.h is POSIX).
Repeating string.h is clutter and may waste time.
I would group openssl/rand.h with the other openssl/*.

> #include <proto.h>
> #define KEY_LEN    32// 32 bytes - 256 bits
> #define KEK_KEY_LEN   5
> #define ITERATION   1000
> 
> //unsigned char salt_value[32]={"5d85947b4292ea6463faf6893451232"}; 
> unsigned char salt_value[KEY_LEN];
> unsigned char AESkey[KEY_LEN];
> unsigned char XTSkey[KEY_LEN];
> u8 fuse_key[KEY_LEN];
> 
Aside: using KEY_LEN as the length of the salt (which is not a key 
of any kind) is somewhat confusing; suggest SALT_LEN instead.
KEK_KEY_LEN is redundant, like "CPU unit"; suggest KEK_LEN.
> 
> void main()

main returning void is not standard and never has been, 
and has no advantage whatsoever over the standard, int.

> {
>    
>     s32 i=0;
>     s32 len =0;
>       u8 *out;
>     u8 *rspHMAC;
>       const s8 pwd[] = "test";
>       s8 rspPKCS5[KEK_KEY_LEN * 2];
>       s32 ret;
>        
Note: these types are not standard or portable. C99 
(still not implemented everywhere, even though C11 has 
just come out) *may* have types of the form int8_t etc.
However, below you treat pwd and rspPKCS5 below as arrays 
of 'plain' char. 'Plain' char is unsigned on some systems, 
so you would either have to make 's8' unsigned which is 
confusing and likely to lead to bugs, or leave s8 signed 
but convert all your accesses to be unsigned, which is 
a good deal of extra work and easy to get wrong.

>       rspHMAC = (unsigned char *) malloc(sizeof(char) * KEY_LEN);
>     out = (unsigned char *) malloc(sizeof(char) * KEK_KEY_LEN);
>       
The return from malloc never needs to be cast in valid C; in C++ 
it does but in C++ you generally shouldn't use malloc at all.
For these small fixed sizes, dynamic allocation is a waste of 
effort and clutter. sizeof(char) is always 1 so it isn't needed, 
although if you consistently follow the pattern of N*sizeof(E) 
for all types it doesn't hurt to be consistent here.

>     RAND_bytes(salt_value, KEY_LEN);
> 
>       
>     printf("\n salt_value[0] = %x; salt_value[31]= %x", salt_value[0],
> salt_value[31]);
>     printf("\n strlen(salt_value) = %d; sizeof(salt_value) = %d\n",
> strlen(salt_value), sizeof(salt_value));
>       //printf("\n salt_value = %s", salt_value);
>       
As I said before, RAND_bytes generates random bytes, 
which can include null and then strlen() is too low;
while your buffer didn't include a null terminator (nor room 
for one) so in general strlen() could be too high -- although 
here salt_value is file-scope static and very likely to be 
followed in memory by the next file-scope static here AESkey 
which appears to be unused and thus still zero, although some 
implementations may follow salt_value by the next _referenced_ 
external static and that may well contain nonnull bytes.

If you want a constant length, use a constant for length.
If you want variable length, determine it and remember it.

But as above if you want to interoperate with the Javascript 
on that website, it's probably easiest to limit yourself to 
bytes which are printable ASCII characters. The simplest way 
is just use columns 4 and 5 (0x40-0x5F). For that do:
  if( RAND_bytes (salt_value,N) <= 0 ) /* ERROR! */
  for( i = 0; i < N; i ++ ) 
    salt_value[i] = (salt_value[i] & 0x1F) | 0x40; 
    // parens redundant but shown for clarity
As above, 32 chars of 5 bits entropy is more than needed 
for security; 50-100 bits (10-20 x 5) is usually plenty 
and usually more than the actual strength of the password.

>     for(i = 0; i < KEY_LEN; i++) {
>         printf("%02x", salt_value[i]);
>         
Here you correctly use the constant length KEY_LEN, 
to convert to hex. But for the Javascript above, 
you don't want hex, you want actual bytes.

>       }
> 
>       ret = PKCS5_PBKDF2_HMAC_SHA1(pwd, strlen(pwd), salt_value,
> strlen(salt_value), ITERATION, KEK_KEY_LEN, out);
>     printf("\n PKCS#5 :");
> 
As above for strlen(salt_value). strlen(pwd) is okay 
given you chose pwd to be valid C string (and further 
a string of printable ASCII, good for that Javascript).
In real use the password should not be hardcoded, nor 
a single dictionary word or other easily guessable value; 
I assume this code is just an example.

>     for(len = 0; len < KEK_KEY_LEN; len++){
>         printf("%02x", out[len]);
>        /* o/p of PKCS5 is stored in buf "out". This cannot be 
> used directly
> as each out[len] will have 2 char
>        but for key gen, we need to consider each char of out 
> as a value. -
> Needs sentence reframing
>          */
>         sprintf(&rspPKCS5[len * 2], "%02x", out[len]);
>    }
> 
This is unsafe as written. You KEK_KEY_LEN=5 bytes into 
rspPKCS5[KEK_KEY_LEN*2] as two hex chars each, _plus 
a null terminator_. Increase it by 1 (at least).

>       printf("\n");
> }
> 
> Sample O/P:
> 
> salt_value[0] = e2; salt_value[31]= 12
>  strlen(salt_value) = 32; sizeof(salt_value) = 32
> e258017933f3e629a4166cece78f3162a3b0b7edb2e94c93d76fe6c38198ea12
>  PKCS#5 :7d7ec9f411
> 
> Website result:
> The derived 40-bit key is: a5caf6a0d3
> 
> 
> 

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

Reply via email to