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