00001 
00026 #include "dh_tool.h"
00027 
00028 
00029 #ifdef ENABLE_SSL
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00043 
00044 
00045 
00060 int  save_DHspki_with_private(Buffer pki, FILE* fp, DH* dhkey)
00061 {    
00062     unsigned int  md;
00063     Buffer pv;
00064 
00065     if (fp==NULL || dhkey==NULL) return FALSE;
00066 
00067     md = JBXL_FIO_SPKI | JBXL_FIO_ORIGINAL;
00068     if (!save_tagged_Buffer(pki, fp, md, FALSE)) return FALSE;
00069 
00070     pv = get_DHprivatekey(dhkey);
00071     if (pv.buf==NULL) return FALSE;
00072 
00073     md = JBXL_FIO_PRIV_KEY | JBXL_FIO_ORIGINAL;
00074     if (!save_tagged_Buffer(pv,  fp, md, FALSE)) return FALSE;
00075     free_Buffer(&pv);
00076 
00077     return  TRUE;
00078 }
00079 
00080 
00081 
00091 Buffer  read_DHspki_with_private(FILE* fp, DH** p_dhkey)
00092 {
00093     int  n = 0, code;
00094     unsigned int  md;
00095     Buffer  pp, pv, pk, gk, yk;
00096 
00097     pp = init_Buffer();
00098     if (fp==NULL) return pp;
00099 
00100     md = JBXL_FIO_SPKI | JBXL_FIO_ORIGINAL;
00101     pp = read_tagged_Buffer(fp, &md);
00102     if (pp.buf==NULL) return pp;
00103 
00104     if (*p_dhkey!=NULL) DH_free(*p_dhkey);
00105     *p_dhkey = DH_new();
00106     if (*p_dhkey==NULL) {
00107         free_Buffer(&pp);
00108         return pp;
00109     }
00110     
00111     pk = get_DHPkey(pp);
00112     gk = get_DHGkey(pp);
00113     yk = get_DHYkey(pp);
00114 
00115 #if OPENSSL_VERSION_NUMBER < 0x10101000L
00116     
00117     (*p_dhkey)->p = BN_bin2bn((const unsigned char*)(pk.buf), pk.vldsz, NULL);
00118     (*p_dhkey)->g = BN_bin2bn((const unsigned char*)(gk.buf), gk.vldsz, NULL);
00119     (*p_dhkey)->pub_key = BN_bin2bn((const unsigned char*)(yk.buf), yk.vldsz, NULL);
00120 #else
00121     
00122     BIGNUM* dhp_bn = BN_bin2bn((const unsigned char*)(pk.buf), pk.vldsz, NULL);
00123     BIGNUM* dhg_bn = BN_bin2bn((const unsigned char*)(gk.buf), gk.vldsz, NULL);
00124     BIGNUM* dhy_bn = BN_bin2bn((const unsigned char*)(gk.buf), gk.vldsz, NULL);
00125 
00126     if (dhp_bn!=NULL && dhg_bn!=NULL && dhy_bn!=NULL) {
00127         DH_set0_pqg(*p_dhkey, dhp_bn, NULL, dhg_bn);
00128         DH_set0_key(*p_dhkey, dhy_bn, NULL);
00129     }
00130     else {
00131         DH_free(*p_dhkey);
00132         *p_dhkey = NULL;
00133     }
00134 #endif
00135 
00136     free_Buffer(&pk);
00137     free_Buffer(&gk);
00138     free_Buffer(&yk);
00139 
00140     
00141     if (*p_dhkey!=NULL) n = DH_check(*p_dhkey, &code);
00142     if (n!=1 || code!=0) {
00143         if (*p_dhkey!=NULL) DH_free(*p_dhkey);
00144         free_Buffer(&pp);
00145         return pp;
00146     }
00147 
00148     
00149     md = JBXL_FIO_PRIV_KEY | JBXL_FIO_ORIGINAL;
00150     pv = read_tagged_Buffer(fp, &md);
00151     if (pv.buf==NULL) {
00152         if (*p_dhkey!=NULL) DH_free(*p_dhkey);
00153         free_Buffer(&pp);
00154         return pp;
00155     }
00156 
00157 #if OPENSSL_VERSION_NUMBER < 0x10101000L
00158     (*p_dhkey)->priv_key = BN_bin2bn((const unsigned char*)(pv.buf), pv.vldsz, NULL);
00159 #else
00160     BIGNUM* priv_key = BN_bin2bn((const unsigned char*)(pv.buf), pv.vldsz, NULL);
00161     DH_set0_key(*p_dhkey, NULL, priv_key);
00162 #endif
00163 
00164     free_Buffer(&pv);
00165 
00166     return  pp;
00167 }
00168 
00169 
00170 
00191 Buffer  get_DHspki_ff(char* filename, int ks, DH** p_dhkey)
00192 {
00193     Buffer  pki;
00194     FILE*   fp;
00195 
00196     pki = init_Buffer();
00197     if (filename==NULL || p_dhkey==NULL) return pki;
00198 
00199     if (file_exist(filename)) {
00200         
00201         fp = fopen(filename, "rb");
00202         pki = read_DHspki_with_private(fp, p_dhkey);
00203         fclose(fp);
00204         
00205         if (pki.buf!=NULL) {
00206 #if OPENSSL_VERSION_NUMBER < 0x10101000L
00207             if (DH_size(*p_dhkey)<(ks+7)/8 || (*p_dhkey)->priv_key==NULL) free_Buffer(&pki);    
00208 #else
00209             const BIGNUM* priv_key = DH_get0_priv_key(*p_dhkey);
00210             if (DH_size(*p_dhkey)<(ks+7)/8 || priv_key==NULL) free_Buffer(&pki);              
00211 #endif
00212         }
00213     }
00214 
00215     if (pki.buf==NULL) {
00216         
00217         pki = gen_DHspki(ks, p_dhkey);
00218         
00219 
00220         fp = file_chmod_open(filename, (char*)"w", S_IRUSR | S_IWUSR);
00221         if (fp!=NULL) {
00222             save_DHspki_with_private(pki, fp, *p_dhkey);
00223             fclose(fp);
00224         }
00225     }
00226 
00227     
00228     
00229     
00230     
00231     
00232     
00233     return pki;
00234 }
00235 
00236 
00237 
00248 Buffer  gen_DHspki(int ks, DH** p_dhkey)
00249 {
00250     int  sz, n, code;
00251     Buffer px, pp, pk;
00252 
00253     pk = init_Buffer();
00254     if (p_dhkey==NULL) return pk;
00255 
00256     
00257     
00258     if (!RAND_load_file("/dev/urandom", 1024)) return pk;
00259 
00260     
00261     do {
00262         if (*p_dhkey!=NULL) DH_free(*p_dhkey);
00263         *p_dhkey = DH_new();
00264 
00265 #if OPENSSL_VERSION_NUMBER < 0x10101000L
00266         *p_dhkey = DH_generate_parameters(ks, DH_GENERATOR_2, NULL, NULL);
00267 #else
00268         n = DH_generate_parameters_ex(*p_dhkey, ks, DH_GENERATOR_2, NULL);
00269 #endif
00270         n = DH_check(*p_dhkey, &code);
00271     } while (n!=1 || code!=0);
00272 
00273     
00274     sz = DH_generate_key(*p_dhkey);                 
00275     if (sz==0) {
00276         DH_free(*p_dhkey);
00277         *p_dhkey = NULL;
00278         return pk;
00279     }
00280 
00281     
00282     sz = i2d_DHparams(*p_dhkey, NULL);              
00283     pp = px = make_Buffer(sz);                      
00284     if (pp.buf==NULL) {
00285         DH_free(*p_dhkey);
00286         *p_dhkey = NULL;
00287         return pk;
00288     }
00289     pp.vldsz = i2d_DHparams(*p_dhkey, &(px.buf));   
00290                                                     
00291 
00292 #if OPENSSL_VERSION_NUMBER < 0x10101000L
00293     sz = BN_num_bytes((*p_dhkey)->pub_key);
00294 #else
00295     const BIGNUM* pub_key = DH_get0_pub_key(*p_dhkey);
00296     sz = BN_num_bytes(pub_key);
00297 #endif
00298 
00299     px = make_Buffer(sz);
00300     if (px.buf==NULL) {
00301         DH_free(*p_dhkey);
00302         *p_dhkey = NULL;
00303         free_Buffer(&pp);
00304         return pk;
00305     }
00306 
00307 #if OPENSSL_VERSION_NUMBER < 0x10101000L
00308     px.vldsz = BN_bn2bin((*p_dhkey)->pub_key, px.buf);
00309 #else
00310     px.vldsz = BN_bn2bin(pub_key, px.buf);
00311 #endif
00312 
00313     pk = join_DHpubkey(pp, px);                    
00314 
00315     free_Buffer(&pp);
00316     free_Buffer(&px);
00317 
00318     return pk;
00319 }
00320 
00321 
00322 
00335 Buffer  gen_DHspki_fs(Buffer pki, DH** p_dhkey)
00336 {
00337     int  sz, n = 0, code;
00338     Buffer px, pp, pk;
00339     Buffer pkey, gkey;
00340 
00341     
00342     pk = init_Buffer();
00343     if (p_dhkey==NULL) return pk;
00344     
00345     if (*p_dhkey!=NULL) DH_free(*p_dhkey);
00346     *p_dhkey = DH_new();
00347     if (*p_dhkey==NULL) return pk;
00348 
00349     pkey = get_DHPkey(pki);
00350     gkey = get_DHGkey(pki);
00351     if (pkey.buf==NULL || gkey.buf==NULL) {
00352         free_Buffer(&pkey);
00353         free_Buffer(&gkey);
00354         DH_free(*p_dhkey);
00355         *p_dhkey = NULL;
00356         return pk;
00357     }
00358 
00359 #if OPENSSL_VERSION_NUMBER < 0x10101000L
00360     (*p_dhkey)->p = BN_bin2bn((const unsigned char*)(pkey.buf), pkey.vldsz, NULL);
00361     (*p_dhkey)->g = BN_bin2bn((const unsigned char*)(gkey.buf), gkey.vldsz, NULL);
00362 #else
00363     BIGNUM* dhp_bn = BN_bin2bn((const unsigned char*)(pkey.buf), pkey.vldsz, NULL);
00364     BIGNUM* dhg_bn = BN_bin2bn((const unsigned char*)(gkey.buf), gkey.vldsz, NULL);
00365     
00366     if (dhp_bn!=NULL && dhg_bn!=NULL) {
00367         DH_set0_pqg(*p_dhkey, dhp_bn, NULL, dhg_bn);
00368     }
00369     else {
00370         DH_free(*p_dhkey);
00371         *p_dhkey = NULL;
00372     }
00373     
00374     
00375 #endif
00376 
00377     free_Buffer(&pkey);
00378     free_Buffer(&gkey);
00379 
00380     
00381     if (*p_dhkey!=NULL) n = DH_check(*p_dhkey, &code);
00382     if (n!=1 || code!=0) {
00383         if (*p_dhkey!=NULL) DH_free(*p_dhkey);
00384         *p_dhkey = NULL;
00385         return pk;
00386     }
00387 
00388     sz = DH_generate_key(*p_dhkey);
00389     if (sz==0) {
00390         DH_free(*p_dhkey);
00391         *p_dhkey = NULL;
00392         return pk;
00393     }
00394 
00395     
00396     sz = i2d_DHparams(*p_dhkey, NULL);                  
00397     pp = px = make_Buffer(sz);                          
00398     if (pp.buf==NULL) {
00399         DH_free(*p_dhkey);
00400         *p_dhkey = NULL;
00401         return pk;
00402     }
00403     pp.vldsz = i2d_DHparams(*p_dhkey, &(px.buf));       
00404                                                         
00405 #if OPENSSL_VERSION_NUMBER < 0x10101000L
00406     sz = BN_num_bytes((*p_dhkey)->pub_key);
00407 #else
00408     const BIGNUM* pub_key = DH_get0_pub_key(*p_dhkey);
00409     sz = BN_num_bytes(pub_key);
00410 #endif
00411 
00412     px = make_Buffer(sz);
00413     if (px.buf==NULL) {
00414         DH_free(*p_dhkey);
00415         *p_dhkey = NULL;
00416         free_Buffer(&pp);
00417         return px;
00418     }
00419 
00420 #if OPENSSL_VERSION_NUMBER < 0x10101000L
00421     px.vldsz = BN_bn2bin((*p_dhkey)->pub_key, px.buf);  
00422 #else
00423     px.vldsz = BN_bn2bin(pub_key, px.buf);              
00424 #endif
00425 
00426     pk = join_DHpubkey(pp, px);                         
00427 
00428     free_Buffer(&pp);
00429     free_Buffer(&px);
00430 
00431     return pk;
00432 }
00433 
00434 
00435 
00450 Buffer get_DHsharedkey(Buffer pki, DH* dhkey)
00451 {
00452     Buffer  ykey, skey;
00453     
00454     skey = init_Buffer();
00455     ykey = get_DHYkey(pki);
00456     if (ykey.buf==NULL) return skey;
00457 
00458     skey = get_DHsharedkey_fY(ykey, dhkey);
00459     
00460     free_Buffer(&ykey);
00461     return skey;
00462 }
00463 
00464 
00465 
00480 Buffer  get_DHsharedkey_fY(Buffer ykey, DH* dhkey)
00481 {
00482     int sz;
00483     Buffer  buf;
00484 
00485     buf = init_Buffer();
00486     if (dhkey==NULL) return buf;
00487 
00488     BIGNUM* yk = BN_bin2bn((const unsigned char*)(ykey.buf), ykey.vldsz, NULL);
00489 
00490     sz  = DH_size(dhkey);
00491     buf = make_Buffer(sz);
00492     buf.vldsz = sz;
00493 
00494     BN_free(yk);
00495     return buf;
00496 }
00497 
00498 
00499 
00520 Buffer  get_DHYkey(Buffer param)
00521 {
00522     int     i, lp, sz=0;
00523     Buffer  pp;
00524     pp = init_Buffer();
00525 
00526     sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
00527     if (sz<0) return pp;
00528 
00529     sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
00530     if (sz<0) return pp;
00531     sz = sz + lp;
00532 
00533     sz = skip_DER_node(param, JBXL_ASN1_BIT, sz, &lp);
00534     if (sz<0) return pp;
00535     sz++;                        
00536 
00537     sz = skip_DER_node(param, JBXL_ASN1_INT, sz, &lp);
00538     if (sz<0) return pp;
00539 
00540     pp = make_Buffer(lp);
00541     if (pp.buf==NULL) return pp;
00542     for (i=0; i<lp; i++) pp.buf[i] = param.buf[sz+i];
00543     pp.vldsz = lp;
00544     return pp;
00545 }
00546 
00547 
00548 
00569 Buffer  get_DHPkey(Buffer param)
00570 {
00571     int     i, lp, sz=0;
00572     Buffer  pp;
00573     pp = init_Buffer();
00574 
00575     sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
00576     if (sz<0) return pp;
00577 
00578     sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
00579     if (sz<0) return pp;
00580 
00581     sz = skip_DER_node(param, JBXL_ASN1_OBJ, sz, &lp);
00582     if (sz<0) return pp;
00583     sz = sz + lp;
00584 
00585     sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
00586     if (sz<0) return pp;
00587 
00588     sz = skip_DER_node(param, JBXL_ASN1_INT, sz, &lp);
00589     if (sz<0) return pp;
00590 
00591     pp = make_Buffer(lp);
00592     if (pp.buf==NULL) return pp;
00593     for (i=0; i<lp; i++) pp.buf[i] = param.buf[sz+i];
00594     pp.vldsz = lp;
00595     return pp;
00596 }
00597 
00598 
00599 
00621 Buffer  get_DHGkey(Buffer param)
00622 {
00623     int     i, lp, sz=0;
00624     Buffer  pp;
00625     pp = init_Buffer();
00626 
00627     sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
00628     if (sz<0) return pp;
00629 
00630     sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
00631     if (sz<0) return pp;
00632 
00633     sz = skip_DER_node(param, JBXL_ASN1_OBJ, sz, &lp);
00634     if (sz<0) return pp;
00635     sz = sz + lp;
00636 
00637     sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
00638     if (sz<0) return pp;
00639 
00640     sz = skip_DER_node(param, JBXL_ASN1_INT, sz, &lp);
00641     if (sz<0) return pp;
00642     sz = sz + lp;
00643 
00644     sz = skip_DER_node(param, JBXL_ASN1_INT, sz, &lp);
00645     if (sz<0) return pp;
00646 
00647     pp = make_Buffer(lp);
00648     if (pp.buf==NULL) return pp;
00649     for (i=0; i<lp; i++) pp.buf[i] = param.buf[sz+i];
00650     pp.vldsz = lp;
00651     return pp;
00652 }
00653 
00654 
00655 
00676 Buffer  get_DHalgorism(Buffer param)
00677 {
00678     int     i, lp, sz=0;
00679     Buffer  pp;
00680     pp = init_Buffer();
00681 
00682     sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
00683     if (sz<0) return pp;
00684 
00685     sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, sz, &lp);
00686     if (sz<0) return pp;
00687 
00688     sz = skip_DER_node(param, JBXL_ASN1_OBJ, sz, &lp);
00689     if (sz<0) return pp;
00690 
00691     pp = make_Buffer(lp);
00692     if (pp.buf==NULL) return pp;
00693     for (i=0; i<lp; i++) pp.buf[i] = param.buf[sz+i];
00694     pp.vldsz = lp;
00695     return pp;
00696 }
00697 
00698 
00707 Buffer  get_DHprivatekey(DH* dhkey)
00708 {
00709     int    sz;
00710     Buffer pv;
00711  
00712 #if OPENSSL_VERSION_NUMBER < 0x10101000L
00713     sz = BN_num_bytes(dhkey->priv_key);
00714 
00715 #else
00716     const BIGNUM* priv_key = DH_get0_pub_key(dhkey);
00717     sz = BN_num_bytes(priv_key);
00718 #endif
00719 
00720     pv = make_Buffer(sz);
00721     if (pv.buf==NULL) return pv;
00722 
00723 #if OPENSSL_VERSION_NUMBER < 0x10101000L
00724     pv.vldsz = BN_bn2bin(dhkey->priv_key, pv.buf);
00725 
00726 #else
00727     pv.vldsz = BN_bn2bin(priv_key, pv.buf);
00728 #endif
00729 
00730     return pv;
00731 }
00732 
00733 
00734 
00767 Buffer  join_DHpubkey(Buffer param, Buffer key)
00768 {
00769 
00770     unsigned char dh_algor[]={0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x03,0x01};    
00771                                             
00772     int len_dh_algor = 11;
00773 
00774     int ls, lp, la, sz;
00775     Buffer  px, pp, pm;
00776 
00777     
00778     pp = init_Buffer();
00779     sz = skip_DER_node(param, JBXL_ASN1_SEQ_CNSTRCTD, 0, &lp);
00780     if (sz<0) return pp;
00781 
00782     pp.buf   = param.buf   + sz;
00783     pp.bufsz = param.bufsz - sz;
00784     pp.vldsz = param.vldsz - sz;
00785 
00786     
00787     px = int2bin_DER(key.vldsz*8-1);
00788     pm = node2DER(px, JBXL_ASN1_INT);
00789     ls = pm.vldsz;
00790     free_Buffer(&px);
00791 
00792     
00793     px = make_Buffer(lp+ls); 
00794     memcpy(px.buf,    pp.buf, lp);
00795     memcpy(px.buf+lp, pm.buf, ls);  
00796     px.vldsz = lp + ls;
00797     free_Buffer(&pm);              
00798     pm = node2DER(px, JBXL_ASN1_SEQ_CNSTRCTD); 
00799     ls = pm.vldsz;
00800     free_Buffer(&px);
00801 
00802     
00803     la = len_dh_algor; 
00804     pp = make_Buffer(ls+la); 
00805     memcpy(pp.buf,  dh_algor, la);
00806     memcpy(pp.buf+la, pm.buf, ls);
00807     pp.vldsz = ls + la;
00808     free_Buffer(&pm);         
00809     px = node2DER(pp, JBXL_ASN1_SEQ_CNSTRCTD);
00810     ls = px.vldsz;
00811     free_Buffer(&pp);  
00812 
00813     
00814     pm = node2DER(key, JBXL_ASN1_INT);
00815     pp = node2DER(pm,  JBXL_ASN1_BIT);
00816     lp = pp.vldsz;
00817     free_Buffer(&pm); 
00818     pm = make_Buffer(ls+lp);
00819     memcpy(pm.buf,    px.buf, ls);
00820     memcpy(pm.buf+ls, pp.buf, lp);
00821     pm.vldsz = ls + lp;
00822     free_Buffer(&px);
00823     free_Buffer(&pp);  
00824 
00825     pp = node2DER(pm, JBXL_ASN1_SEQ_CNSTRCTD);
00826     free_Buffer(&pm);
00827     return pp;
00828 }
00829 
00830 
00831 #endif