Hi,
Thank you all for your quick responses. I am using openssl 1.0.1 on a Linux 
machine. The DH_new() works correctly in my machine. It does not return NULL. 
Only the problem occurs in these lines-

> >
> >         BN_bin2bn(parmp,strlen(parmp), dhPar2->p);
> >         BN_bin2bn(parmg,strlen(parmg), dhPar2->g);

For unknown reasons, it does not convert, and place the BIGNUM in dhPar2->p or 
dhPar2->g. Instead I use PEM_write_bio_DHparams() and PEM_read_bio_DHparams(), 
and it works like charm.

Thank you for your help.






On Tuesday, January 21, 2014 6:05 AM, Dave Thompson <dthomp...@prinpay.com> 
wrote:
 
> From: owner-openssl-us...@openssl.org  On Behalf Of Matt Caswell
> Sent: Monday, January 20, 2014 15:45

> On 20 January 2014 15:34, khan wahid <rr...@yahoo.com> wrote:
> > Hi,
> > I am trying to implement DH key exchage using openssl in the same
program,
> > so I generate DH parameters once, and then transfer the p and g to
another
> > DH object, here is my code-
> >
<snip>
> > void hexprint(unsigned char *printBuf, int len)
<snip>
> > int main(int argc, char *argv[])
> >     {
> >         DH *dhPar=DH_new();
> >         DH *dhPar2=DH_new();
> >         time_t rt;
> >         srand((unsigned) time(&rt));
> >
openssl doesn't use the C-library RNG rand(). It has its own RAND_*,
which is automatically seeded (for generate) with time, and (for all 
SSLeay) other possibly platform-dependent stuff like /dev/random.
C rand() isn't designed to be, and usually(?) isn't, a CSPRNG.

> >         unsigned char *dhSec1;
> >         unsigned char *dhSec2;
> >         printf("Generate parameter \n");
> >         DH_generate_parameters_ex(dhPar, 1024, DH_GENERATOR_2, 0);
> >
> >         unsigned char *parmp=malloc(sizeof(unsigned char *) *
> > BN_num_bytes(dhPar->p));
> >         unsigned char *parmg=malloc(sizeof(unsigned char *) *
> > BN_num_bytes(dhPar->g));
> 
> You should check the return values of these calls to check that they
> have worked! However I will assume that this is not your problem (see
> below)...
> 
Also the size is wrong (albeit on the safe side). You actually want 
BN_num_bytes(whatever) times sizeof (unsigned char /*not ptr*/) 
which is always 1 on every C everywhere and thus can be omitted.
The idiom is T * ptr = malloc (nelem * sizeof (T /* not T* */)) or 
T * ptr = malloc ( nelem * sizeof *ptr ). The latter can be more 
robust in getting the type correct if the malloc and assignment are 
separated in the code, if you are still using C90 (e.g. Microsoft) 
or prefer the classic organization of all declarations at the top.

> >         memset(parmp, 0, BN_num_bytes(dhPar->p));
> >         memset(parmg, 0, BN_num_bytes(dhPar->g));
> >
> >         BN_bn2bin(dhPar->p,parmp);
> >         BN_bn2bin(dhPar->g,parmg);
> >
> >         BN_bin2bn(parmp,strlen(parmp), dhPar2->p);
> >         BN_bin2bn(parmg,strlen(parmg), dhPar2->g);
> 
> You should not use strlen to find the length of binary data. This
> could potentially cause a seg fault.
> 
Or a silently incorrect value, which is harder to debug.

> You have not said what version of openssl you are running, so I have
> checked the standard default behaviour of Openssl 1.0.1f. DH_new does

I'm pretty sure this area hasn't changed in a long time.

> not allocate the BIGNUMs for p and g. They are set to NULL. The call
> to BN_bin2bn will check the value of its 3rd argument. If it is null
> it will allocate a BIGNUM and return it. Therefore this is what is
> happening to your code. The values of p and g will remain as NULL, and
> the allocated BIGNUMs are being ignored by your code.
> 
> >
> >         DH_generate_key(dhPar);
> 
> This is clearly going to fail (with a seg fault) because the
> parameters have not been set (as noted above).
> 
Additional issues:

openssl current (PKCS3) DH parameters in general can contain 
L (xsize) in addition to p and g, although parameters generated 
by (current) DH_generate_parameters[_ex] don't.
Reportedly 1.0.2 will support X9.42 parameters with full q.

Within one process' memory (as this is) instead of converting 
BN to external form and then back, you can just call BN_dup.
And for this whole use case you can just call DHparams_dup.

In real use you more often need to copy DH parameters 
from one process to another, often via storage in between. 
openssl supports the PKCS3 format for this, with i2d/d2i 
or PEM_read/write, which if you can use it is easier and 
probably safer than designing and coding your own.

> If you have not already found it, you should check this page which
> gives details and code samples of working with DH:
> 
> http://wiki.openssl.org/index.php/Diffie_Hellman
> 
Apparently not much tested; i2d_DHparams_bio 
writes or "sends" only the parameters not any key -- 
even though the same DH struct contains both/all.
There is (currently) no DH_ level routines to read and write 
a public OR private key, but the EVP_ generic PUBKEY and 
PrivateKey routines do so, as X.509 SubjectPublickKeyInfo 
aka SPKI or PKCS#8, which include params plus y or x and y.

There are three possible cases:
- ephemeral parameters: A must send new parameters 
AND yA to peer, who needs to send back only yB (although 
it may be convenient to embed in SPKI)
- static but undistributed parameters: effectively the same
- pre-distributed parameters: A only needs to send yA,
but may embed in SPKI; B doesn't need to wait for A to 
get parameters but may wait anyway, and only needs 
to send yB but may embed in SPKI.

Finally, 1024 today doesn't have much margin of security,
and generally isn't a good idea for new designs. It may be 
needed for compatibility with existing peers or protocols.



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

Reply via email to