XrdCryptosslCipher.cc

Go to the documentation of this file.
00001 // $Id: XrdCryptosslCipher.cc 30949 2009-11-02 16:37:58Z ganis $
00002 
00003 const char *XrdCryptosslCipherCVSID = "$Id: XrdCryptosslCipher.cc 30949 2009-11-02 16:37:58Z ganis $";
00004 /******************************************************************************/
00005 /*                                                                            */
00006 /*                  X r d C r y p t o S s l C i p h e r . c c                 */
00007 /*                                                                            */
00008 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University  */
00009 /*       All Rights Reserved. See XrdInfo.cc for complete License Terms       */
00010 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00011 /*              DE-AC03-76-SFO0515 with the Department of Energy              */
00012 /******************************************************************************/
00013 
00014 /* ************************************************************************** */
00015 /*                                                                            */
00016 /* OpenSSL implementation of XrdCryptoCipher                                  */
00017 /*                                                                            */
00018 /* ************************************************************************** */
00019 #include <string.h>
00020 
00021 #include <XrdSut/XrdSutRndm.hh>
00022 #include <XrdCrypto/XrdCryptosslTrace.hh>
00023 #include <XrdCrypto/XrdCryptosslCipher.hh>
00024 
00025 //#include <openssl/dsa.h>
00026 #include <openssl/bio.h>
00027 #include <openssl/pem.h>
00028 
00029 // ---------------------------------------------------------------------------//
00030 //
00031 // Cipher interface
00032 //
00033 // ---------------------------------------------------------------------------//
00034 
00035 //_____________________________________________________________________________
00036 bool XrdCryptosslCipher::IsSupported(const char *cip)
00037 {
00038    // Check if the specified cipher is supported
00039 
00040    return (EVP_get_cipherbyname(cip) != 0);
00041 }
00042 
00043 //____________________________________________________________________________
00044 XrdCryptosslCipher::XrdCryptosslCipher(const char *t, int l)
00045 {
00046    // Main Constructor
00047    // Complete initialization of a cipher of type t and length l
00048    // The initialization vector is also created
00049    // Used to create ciphers
00050 
00051    valid = 0;
00052    fIV = 0;
00053    lIV = 0;
00054    cipher = 0;
00055    fDH = 0;
00056    deflength = 1;
00057 
00058    // Check and set type
00059    char cipnam[64] = {"bf-cbc"};
00060    if (t && strcmp(t,"default")) {
00061       strcpy(cipnam,t); 
00062       cipnam[63] = 0;
00063    }
00064    cipher = EVP_get_cipherbyname(cipnam);
00065 
00066    if (cipher) {
00067       // Init context
00068       EVP_CIPHER_CTX_init(&ctx);
00069       // Determine key length
00070       l = (l > EVP_MAX_KEY_LENGTH) ? EVP_MAX_KEY_LENGTH : l;
00071       int ldef = EVP_CIPHER_key_length(cipher);
00072       int lgen = (l > ldef) ? l : ldef;
00073       // Generate and set a new key
00074       char *ktmp = XrdSutRndm::GetBuffer(lgen);
00075       if (ktmp) {
00076          valid = 1;
00077          // Try setting the key length
00078          if (l && l != ldef) {
00079             EVP_CipherInit(&ctx, cipher, 0, 0, 1);
00080             EVP_CIPHER_CTX_set_key_length(&ctx,l);
00081             EVP_CipherInit(&ctx, 0, (unsigned char *)ktmp, 0, 1);
00082             if (l == EVP_CIPHER_CTX_key_length(&ctx)) {
00083                // Use the l bytes at ktmp
00084                SetBuffer(l,ktmp);
00085                deflength = 0;
00086             }
00087          }
00088          if (!Length()) {
00089             EVP_CipherInit(&ctx, cipher, (unsigned char *)ktmp, 0, 1);
00090             SetBuffer(ldef,ktmp);
00091          }
00092          // Set also the type
00093          SetType(cipnam);
00094          // Cleanup
00095          delete[] ktmp;
00096       }
00097    }
00098 
00099    // Finally, generate and set a new IV
00100    if (valid)
00101       GenerateIV();
00102 }
00103 
00104 //____________________________________________________________________________
00105 XrdCryptosslCipher::XrdCryptosslCipher(const char *t, int l,
00106                                        const char *k, int liv, const char *iv)
00107 {
00108    // Constructor.
00109    // Initialize a cipher of type t and length l using the key at k and
00110    // the initialization vector at iv.
00111    // Used to import ciphers.
00112    valid = 0;
00113    fIV = 0;
00114    lIV = 0;
00115    fDH = 0;
00116    cipher = 0;
00117    deflength = 1;
00118 
00119    // Check and set type
00120    char cipnam[64] = {"bf-cbc"};
00121    if (t && strcmp(t,"default")) {
00122       strcpy(cipnam,t); 
00123       cipnam[63] = 0;
00124    }
00125    cipher = EVP_get_cipherbyname(cipnam);
00126 
00127    if (cipher) {
00128       // Init context
00129       EVP_CIPHER_CTX_init(&ctx);
00130       // Set the key
00131       SetBuffer(l,k);
00132       if (l != EVP_CIPHER_key_length(cipher))
00133          deflength = 0;
00134       // Set also the type
00135       SetType(cipnam);
00136       // Set validity flag
00137       valid = 1;
00138    }
00139    //
00140    // Init cipher
00141    if (valid) {
00142       //
00143       // Set the IV
00144       SetIV(liv,iv);
00145 
00146       if (deflength) {
00147          EVP_CipherInit(&ctx, cipher, (unsigned char *)Buffer(), 0, 1);
00148       } else {
00149          EVP_CipherInit(&ctx, cipher, 0, 0, 1);
00150          EVP_CIPHER_CTX_set_key_length(&ctx,Length());
00151          EVP_CipherInit(&ctx, 0, (unsigned char *)Buffer(), 0, 1);
00152       }
00153    }
00154 }
00155 
00156 //____________________________________________________________________________
00157 XrdCryptosslCipher::XrdCryptosslCipher(XrdSutBucket *bck)
00158 {
00159    // Constructor from bucket.
00160    // Initialize a cipher of type t and length l using the key at k
00161    // Used to import ciphers.
00162    valid = 0;
00163    fIV = 0;
00164    lIV = 0;
00165    fDH = 0;
00166    cipher = 0;
00167    deflength = 1;
00168 
00169    if (bck && bck->size > 0) {
00170 
00171       // Init context
00172       EVP_CIPHER_CTX_init(&ctx);
00173 
00174       valid = 1;
00175 
00176       kXR_int32 ltyp = 0;
00177       kXR_int32 livc = 0;
00178       kXR_int32 lbuf = 0;
00179       kXR_int32 lp = 0;
00180       kXR_int32 lg = 0;
00181       kXR_int32 lpub = 0;
00182       kXR_int32 lpri = 0;
00183       char *bp = bck->buffer;
00184       int cur = 0;
00185       memcpy(&ltyp,bp+cur,sizeof(kXR_int32));
00186       cur += sizeof(kXR_int32);
00187       memcpy(&livc,bp+cur,sizeof(kXR_int32));
00188       cur += sizeof(kXR_int32);
00189       memcpy(&lbuf,bp+cur,sizeof(kXR_int32));
00190       cur += sizeof(kXR_int32);
00191       memcpy(&lp,bp+cur,sizeof(kXR_int32));
00192       cur += sizeof(kXR_int32);
00193       memcpy(&lg,bp+cur,sizeof(kXR_int32));
00194       cur += sizeof(kXR_int32);
00195       memcpy(&lpub,bp+cur,sizeof(kXR_int32));
00196       cur += sizeof(kXR_int32);
00197       memcpy(&lpri,bp+cur,sizeof(kXR_int32));
00198       cur += sizeof(kXR_int32);
00199       // Type
00200       if (ltyp) {
00201          char *buf = new char[ltyp+1];
00202          if (buf) {
00203             memcpy(buf,bp+cur,ltyp);
00204             buf[ltyp] = 0;
00205             cipher = EVP_get_cipherbyname(buf);
00206             if (!cipher)
00207                cipher = EVP_get_cipherbyname("bf-cbc");
00208             if (cipher) {
00209                // Set the type
00210                SetType(buf);
00211             } else {
00212                valid = 0;
00213             } 
00214             delete[] buf;
00215          } else
00216             valid = 0;
00217          cur += ltyp;
00218       }
00219       // IV
00220       if (livc) {
00221          char *buf = new char[livc];
00222          if (buf) {
00223             memcpy(buf,bp+cur,livc);
00224             cur += livc;
00225             // Set the IV
00226             SetIV(livc,buf);
00227             delete[] buf;
00228          } else
00229             valid = 0;
00230          cur += livc;
00231       }
00232       // buffer
00233       if (lbuf) {
00234          char *buf = new char[lbuf];
00235          if (buf) {
00236             memcpy(buf,bp+cur,lbuf);
00237             // Set the buffer
00238             UseBuffer(lbuf,buf);
00239             if (cipher && lbuf != EVP_CIPHER_key_length(cipher))
00240                deflength = 0;
00241          } else
00242             valid = 0;
00243          cur += lbuf;
00244       }
00245       // DH, if any
00246       if (lp > 0 || lg > 0 || lpub > 0 || lpri > 0) {
00247          if ((fDH = DH_new())) {
00248             char *buf = 0;
00249             // p
00250             if (lp > 0) {
00251                buf = new char[lp+1];
00252                if (buf) {
00253                   memcpy(buf,bp+cur,lp);
00254                   buf[lp] = 0;
00255                   BN_hex2bn(&(fDH->p),buf);
00256                   delete[] buf;
00257                } else
00258                   valid = 0;
00259                cur += lp;
00260             }
00261             // g
00262             if (lg > 0) {
00263                buf = new char[lg+1];
00264                if (buf) {
00265                   memcpy(buf,bp+cur,lg);
00266                   buf[lg] = 0;
00267                   BN_hex2bn(&(fDH->g),buf);
00268                   delete[] buf;
00269                } else
00270                   valid = 0;
00271                cur += lg;
00272             }
00273             // pub_key
00274             if (lpub > 0) {
00275                buf = new char[lpub+1];
00276                if (buf) {
00277                   memcpy(buf,bp+cur,lpub);
00278                   buf[lpub] = 0;
00279                   BN_hex2bn(&(fDH->pub_key),buf);
00280                   delete[] buf;
00281                } else
00282                   valid = 0;
00283                cur += lpub;
00284             }
00285             // priv_key
00286             if (lpri > 0) {
00287                buf = new char[lpri+1];
00288                if (buf) {
00289                   memcpy(buf,bp+cur,lpri);
00290                   buf[lpri] = 0;
00291                   BN_hex2bn(&(fDH->priv_key),buf);
00292                   delete[] buf;
00293                } else
00294                   valid = 0;
00295                cur += lpri;
00296             }
00297             int dhrc = 0;
00298             DH_check(fDH,&dhrc);
00299             if (dhrc == 0)
00300                valid = 1;
00301          } else
00302             valid = 0;
00303       }
00304    }
00305    //
00306    // Init cipher
00307    if (valid) {
00308       if (deflength) {
00309          EVP_CipherInit(&ctx, cipher, (unsigned char *)Buffer(), 0, 1);
00310       } else {
00311          EVP_CipherInit(&ctx, cipher, 0, 0, 1);
00312          EVP_CIPHER_CTX_set_key_length(&ctx,Length());
00313          EVP_CipherInit(&ctx, 0, (unsigned char *)Buffer(), 0, 1);
00314       }
00315    }
00316 }
00317 
00318 //____________________________________________________________________________
00319 XrdCryptosslCipher::XrdCryptosslCipher(int bits, char *pub,
00320                                        int lpub, const char *t)
00321 {
00322    // Constructor for key agreement.
00323    // If pub is not defined, generates a DH full key,
00324    // the public part and parameters can be retrieved using Public().
00325    // The number of random bits to be used in 'bits'.
00326    // If pub is defined with the public part and parameters of the
00327    // counterpart fully initialize a cipher with that information.
00328    // Sets also the name to 't', if different from the default one.
00329    // Used for key agreement.
00330    EPNAME("sslCipher::XrdCryptosslCipher");
00331 
00332    valid = 0;
00333    fIV = 0;
00334    lIV = 0;
00335    fDH = 0;
00336    cipher = 0;
00337    deflength = 1;
00338 
00339    if (!pub) {
00340       DEBUG("generate DH full key");
00341       //
00342       // at least 128 bits
00343       bits = (bits < kDHMINBITS) ? kDHMINBITS : bits; 
00344       //
00345       // Generate params for DH object
00346       if ((fDH = DH_generate_parameters(bits,DH_GENERATOR_5,0,0))) {
00347          int prc = 0;
00348          DH_check(fDH,&prc);
00349          if (prc == 0) {
00350             //
00351             // Generate DH key
00352             if (DH_generate_key(fDH)) {
00353                valid = 1;
00354             } else {
00355                DH_free(fDH);
00356             }
00357          }
00358       }
00359 
00360    } else {
00361       DEBUG("initialize cipher from key-agreement buffer");
00362       //
00363       char *ktmp = 0;
00364       int ltmp = 0;
00365       // Extract string with bignumber
00366       BIGNUM *bnpub = 0;
00367       char *pb = strstr(pub,"---BPUB---");
00368       char *pe = strstr(pub,"---EPUB--"); // one less (pub not null-terminated)
00369       if (pb && pe) {
00370          lpub = (int)(pb-pub);
00371          pb += 10;
00372          *pe = 0;
00373          BN_hex2bn(&bnpub, pb);
00374          *pe = '-';
00375       }
00376       if (bnpub) {
00377          //
00378          // Prepare to decode the input buffer
00379          BIO *biop = BIO_new(BIO_s_mem());
00380          if (biop) {
00381             //
00382             // Write buffer into BIO
00383             BIO_write(biop,pub,lpub);
00384             //
00385             // Create a key object
00386             if ((fDH = DH_new())) {
00387                //
00388                // Read parms from BIO
00389                PEM_read_bio_DHparams(biop,&fDH,0,0);
00390                int prc = 0;
00391                DH_check(fDH,&prc);
00392                if (prc == 0) {
00393                   //
00394                   // generate DH key
00395                   if (DH_generate_key(fDH)) {
00396                      // Now we can compute the cipher
00397                      ktmp = new char[DH_size(fDH)];
00398                      memset(ktmp, 0, DH_size(fDH));
00399                      if (ktmp) {
00400                         if ((ltmp = DH_compute_key((unsigned char *)ktmp,
00401                                                     bnpub,fDH)) > 0)
00402                            valid = 1;
00403                      }
00404                   }
00405                }
00406             }
00407             BIO_free(biop);
00408          }
00409       }
00410       //
00411       // If a valid key has been computed, set the cipher
00412       if (valid) {
00413 
00414          // Check and set type
00415          char cipnam[64] = {"bf-cbc"};
00416          if (t && strcmp(t,"default")) {
00417             strcpy(cipnam,t); 
00418             cipnam[63] = 0;
00419          }
00420          if ((cipher = EVP_get_cipherbyname(cipnam))) {
00421             // Init context
00422             EVP_CIPHER_CTX_init(&ctx);
00423             // At most EVP_MAX_KEY_LENGTH bytes
00424             ltmp = (ltmp > EVP_MAX_KEY_LENGTH) ? EVP_MAX_KEY_LENGTH : ltmp;
00425             int ldef = EVP_CIPHER_key_length(cipher);
00426             // Try setting the key length
00427             if (ltmp != ldef) {
00428                EVP_CipherInit(&ctx, cipher, 0, 0, 1);
00429                EVP_CIPHER_CTX_set_key_length(&ctx,ltmp);
00430                EVP_CipherInit(&ctx, 0, (unsigned char *)ktmp, 0, 1);
00431                if (ltmp == EVP_CIPHER_CTX_key_length(&ctx)) {
00432                   // Use the ltmp bytes at ktmp
00433                   SetBuffer(ltmp,ktmp);
00434                   deflength = 0;
00435                }
00436             }
00437             if (!Length()) {
00438                EVP_CipherInit(&ctx, cipher, (unsigned char *)ktmp, 0, 1);
00439                SetBuffer(ldef,ktmp);
00440             }
00441             // Set also the type
00442             SetType(cipnam);
00443          }
00444       }     
00445       // Cleanup
00446       if (ktmp) delete[] ktmp; ktmp = 0;
00447    }
00448 
00449    // Cleanup, if invalid
00450    if (!valid)
00451       Cleanup();
00452 }
00453 
00454 //____________________________________________________________________________
00455 XrdCryptosslCipher::XrdCryptosslCipher(const XrdCryptosslCipher &c)
00456 {
00457    // Copy Constructor
00458 
00459    // Basics
00460    deflength = c.deflength;
00461    valid = c.valid;
00462    // IV
00463    lIV = 0;
00464    fIV = 0;
00465    SetIV(c.lIV,c.fIV);
00466    // Cipher
00467    cipher = c.cipher;
00468    // Init context
00469    EVP_CIPHER_CTX_init(&ctx);
00470    // Set the key
00471    SetBuffer(c.Length(),c.Buffer());
00472    // Set also the type
00473    SetType(c.Type());
00474    // DH
00475    fDH = 0;
00476    if (valid && c.fDH) {
00477       valid = 0;
00478       if ((fDH = DH_new())) {
00479          if (c.fDH->p) fDH->p = BN_dup(c.fDH->p);
00480          if (c.fDH->g) fDH->g = BN_dup(c.fDH->g);
00481          if (c.fDH->pub_key) fDH->pub_key = BN_dup(c.fDH->pub_key);
00482          if (c.fDH->priv_key) fDH->priv_key = BN_dup(c.fDH->priv_key);
00483          int dhrc = 0;
00484          DH_check(fDH,&dhrc);
00485          if (dhrc == 0)
00486             valid = 1;
00487       }
00488    }
00489 }
00490 
00491 //____________________________________________________________________________
00492 XrdCryptosslCipher::~XrdCryptosslCipher()
00493 {
00494    // Destructor.
00495 
00496    // Cleanup IV
00497    if (fIV)
00498       delete[] fIV;
00499 
00500    // Cleanups
00501    if (valid)
00502       EVP_CIPHER_CTX_cleanup(&ctx);
00503    Cleanup();
00504 }
00505 
00506 //____________________________________________________________________________
00507 void XrdCryptosslCipher::Cleanup()
00508 {
00509    // Cleanup temporary memory
00510 
00511    // Cleanup IV
00512    if (fDH) {
00513       DH_free(fDH);
00514       fDH = 0;
00515    }
00516 }
00517 
00518 //____________________________________________________________________________
00519 bool XrdCryptosslCipher::Finalize(char *pub, int lpub, const char *t)
00520 {
00521    // Finalize cipher during key agreement. Should be called
00522    // for a cipher build with special constructor defining member fDH.
00523    // The buffer pub should contain the public part of the counterpart.
00524    // Sets also the name to 't', if different from the default one.
00525    // Used for key agreement.
00526    EPNAME("sslCipher::Finalize");
00527 
00528    if (!fDH) {
00529       DEBUG("DH undefined: this cipher cannot be finalized"
00530             " by this method");
00531       return 0;
00532    }
00533 
00534    char *ktmp = 0;
00535    int ltmp = 0;
00536    if (pub) {
00537       //
00538       // Extract string with bignumber
00539       BIGNUM *bnpub = 0;
00540       char *pb = strstr(pub,"---BPUB---");
00541       char *pe = strstr(pub,"---EPUB--");
00542       if (pb && pe) {
00543          lpub = (int)(pb-pub);
00544          pb += 10;
00545          *pe = 0;
00546          BN_hex2bn(&bnpub, pb);
00547          *pe = '-';
00548       }
00549       if (bnpub) {
00550          // Now we can compute the cipher
00551          ktmp = new char[DH_size(fDH)];
00552          memset(ktmp, 0, DH_size(fDH));
00553          if (ktmp) {
00554             if ((ltmp =
00555                  DH_compute_key((unsigned char *)ktmp,bnpub,fDH)) > 0)
00556                valid = 1;
00557          }
00558       }
00559       //
00560       // If a valid key has been computed, set the cipher
00561       if (valid) {
00562          // Check and set type
00563          char cipnam[64] = {"bf-cbc"};
00564          if (t && strcmp(t,"default")) {
00565             strcpy(cipnam,t); 
00566             cipnam[63] = 0;
00567          }
00568          if ((cipher = EVP_get_cipherbyname(cipnam))) {
00569             // Init context
00570             EVP_CIPHER_CTX_init(&ctx);
00571             // At most EVP_MAX_KEY_LENGTH bytes
00572             ltmp = (ltmp > EVP_MAX_KEY_LENGTH) ? EVP_MAX_KEY_LENGTH : ltmp;
00573             int ldef = EVP_CIPHER_key_length(cipher);
00574             // Try setting the key length
00575             if (ltmp != ldef) {
00576                EVP_CipherInit(&ctx, cipher, 0, 0, 1);
00577                EVP_CIPHER_CTX_set_key_length(&ctx,ltmp);
00578                EVP_CipherInit(&ctx, 0, (unsigned char *)ktmp, 0, 1);
00579                if (ltmp == EVP_CIPHER_CTX_key_length(&ctx)) {
00580                   // Use the ltmp bytes at ktmp
00581                   SetBuffer(ltmp,ktmp);
00582                   deflength = 0;
00583                }
00584             }
00585             if (!Length()) {
00586                EVP_CipherInit(&ctx, cipher, (unsigned char *)ktmp, 0, 1);
00587                SetBuffer(ldef,ktmp);
00588             }
00589             // Set also the type
00590             SetType(cipnam);
00591          }
00592       }     
00593       // Cleanup
00594       if (ktmp) delete[] ktmp; ktmp = 0;
00595    }
00596 
00597    // Cleanup, if invalid
00598    if (!valid)
00599       Cleanup();
00600 
00601    // We are done
00602    return valid;
00603 }
00604 
00605 //_____________________________________________________________________________
00606 int XrdCryptosslCipher::Publen()
00607 {
00608    // Minimu length of export format of public key 
00609    static int lhdr = strlen("-----BEGIN DH PARAMETERS-----"
00610                             "-----END DH PARAMETERS-----") + 3;
00611    if (fDH) {
00612       // minimum length of the core is 22 bytes
00613       int l = 2*DH_size(fDH);
00614       if (l < 22) l = 22;
00615       // for headers
00616       l += lhdr;
00617       // some margin
00618       return (l+20);
00619    } else
00620       return 0;
00621 }
00622 
00623 //_____________________________________________________________________________
00624 char *XrdCryptosslCipher::Public(int &lpub)
00625 {
00626    // Return buffer with the public part of the DH key and the shared
00627    // parameters; lpub contains the length of the meaningful bytes.
00628    // Buffer should be deleted by the caller.
00629    static int lhend = strlen("-----END DH PARAMETERS-----");
00630 
00631    if (fDH) {
00632       //
00633       // Calculate and write public key hex
00634       char *phex = BN_bn2hex(fDH->pub_key);
00635       int lhex = strlen(phex);
00636       //
00637       // Prepare bio to export info buffer
00638       BIO *biop = BIO_new(BIO_s_mem());
00639       if (biop) {
00640          int ltmp = Publen() + lhex + 20;
00641          char *pub = new char[ltmp];
00642          if (pub) {
00643             // Write parms first
00644             PEM_write_bio_DHparams(biop,fDH);
00645             // Read key from BIO to buf
00646             BIO_read(biop,(void *)pub,ltmp);
00647             BIO_free(biop);
00648             // Add public key
00649             char *p = strstr(pub,"-----END DH PARAMETERS-----");
00650             // Buffer length up to now
00651             lpub = (int)(p - pub) + lhend + 1;
00652             if (phex && p) {
00653                // position at the end
00654                p += (lhend+1);
00655                // Begin of public key hex
00656                strncpy(p,"---BPUB---",10);
00657                p += 10;
00658                // Calculate and write public key hex
00659                strncpy(p,phex,lhex);
00660                OPENSSL_free(phex);
00661                // End of public key hex
00662                p += lhex;
00663                strncpy(p,"---EPUB---",10);
00664                // Calculate total length
00665                lpub += (20 + lhex);
00666             } else {
00667                if (phex) OPENSSL_free(phex);
00668             }
00669             // return
00670             return pub;
00671          }
00672       } else {
00673          if (phex) OPENSSL_free(phex);
00674       }
00675    }
00676 
00677    lpub = 0;
00678    return (char *)0;
00679 }
00680 
00681 //_____________________________________________________________________________
00682 void XrdCryptosslCipher::PrintPublic(BIGNUM *pub)
00683 {
00684    // Print public part
00685 
00686    //
00687    // Prepare bio to export info buffer
00688    BIO *biop = BIO_new(BIO_s_mem());
00689    if (biop) {
00690       // Use a DSA structure to export the public part
00691       DSA *dsa = DSA_new();
00692       if (dsa) {
00693          dsa->pub_key = BN_dup(pub);
00694          // Write public key to BIO
00695          PEM_write_bio_DSA_PUBKEY(biop,dsa);
00696          // Read key from BIO to buf
00697          int lpub = Publen();
00698          char *bpub = new char[lpub];
00699          if (bpub) {
00700             BIO_read(biop,(void *)bpub,lpub);
00701             cerr << bpub << endl;
00702             delete[] bpub;
00703          }
00704          DSA_free(dsa);
00705       }
00706       BIO_free(biop);
00707    }
00708 }
00709 
00710 //_____________________________________________________________________________
00711 XrdSutBucket *XrdCryptosslCipher::AsBucket()
00712 {
00713    // Return pointer to a bucket created using the internal information
00714    // serialized
00715    // The bucket is responsible for the allocated memory
00716 
00717    XrdSutBucket *buck = (XrdSutBucket *)0;
00718 
00719    if (valid) {
00720 
00721       // Serialize .. total length
00722       kXR_int32 lbuf = Length();
00723       kXR_int32 ltyp = Type() ? strlen(Type()) : 0;
00724       kXR_int32 livc = lIV;
00725       char *cp = (fDH && fDH->p) ? BN_bn2hex(fDH->p) : 0;
00726       char *cg = (fDH && fDH->g) ? BN_bn2hex(fDH->g) : 0;
00727       char *cpub = (fDH && fDH->pub_key) ? BN_bn2hex(fDH->pub_key) : 0;
00728       char *cpri = (fDH && fDH->priv_key) ? BN_bn2hex(fDH->priv_key) : 0;
00729       kXR_int32 lp = cp ? strlen(cp) : 0;
00730       kXR_int32 lg = cg ? strlen(cg) : 0;
00731       kXR_int32 lpub = cpub ? strlen(cpub) : 0;
00732       kXR_int32 lpri = cpri ? strlen(cpri) : 0;
00733       int ltot = 7*sizeof(kXR_int32) + ltyp + Length() + livc +
00734                  lp + lg + lpub + lpri;
00735       char *newbuf = new char[ltot];
00736       if (newbuf) {
00737          int cur = 0;
00738          memcpy(newbuf+cur,&ltyp,sizeof(kXR_int32));
00739          cur += sizeof(kXR_int32);
00740          memcpy(newbuf+cur,&livc,sizeof(kXR_int32));
00741          cur += sizeof(kXR_int32);
00742          memcpy(newbuf+cur,&lbuf,sizeof(kXR_int32));
00743          cur += sizeof(kXR_int32);
00744          memcpy(newbuf+cur,&lp,sizeof(kXR_int32));
00745          cur += sizeof(kXR_int32);
00746          memcpy(newbuf+cur,&lg,sizeof(kXR_int32));
00747          cur += sizeof(kXR_int32);
00748          memcpy(newbuf+cur,&lpub,sizeof(kXR_int32));
00749          cur += sizeof(kXR_int32);
00750          memcpy(newbuf+cur,&lpri,sizeof(kXR_int32));
00751          cur += sizeof(kXR_int32);
00752          if (Type()) {
00753             memcpy(newbuf+cur,Type(),ltyp);
00754             cur += ltyp;
00755          }
00756          if (fIV) {
00757             memcpy(newbuf+cur,fIV,livc);
00758             cur += livc;
00759          }
00760          if (Buffer()) {
00761             memcpy(newbuf+cur,Buffer(),lbuf);
00762             cur += lbuf;
00763          }
00764          if (cp) {
00765             memcpy(newbuf+cur,cp,lp);
00766             cur += lp;
00767             OPENSSL_free(cp);
00768          }
00769          if (cg) {
00770             memcpy(newbuf+cur,cg,lg);
00771             cur += lg;
00772             OPENSSL_free(cg);
00773          }
00774          if (cpub) {
00775             memcpy(newbuf+cur,cpub,lpub);
00776             cur += lpub;
00777             OPENSSL_free(cpub);
00778          }
00779          if (cpri) {
00780             memcpy(newbuf+cur,cpri,lpri);
00781             cur += lpri;
00782             OPENSSL_free(cpri);
00783          }
00784          // The bucket now
00785          buck = new XrdSutBucket(newbuf,ltot,kXRS_cipher);
00786       }
00787    }
00788 
00789    return buck;
00790 }
00791 
00792 //____________________________________________________________________________
00793 void XrdCryptosslCipher::SetIV(int l, const char *iv)
00794 {
00795    // Set IV from l bytes at iv
00796 
00797    if (fIV) {
00798       delete[] fIV;
00799       fIV = 0;
00800       lIV = 0;
00801    }
00802 
00803    if (iv && l > 0) {
00804       fIV = new char[l];
00805       if (fIV) {
00806          memcpy(fIV,iv,l);
00807          lIV = l;
00808       }
00809    }
00810 }
00811 
00812 //____________________________________________________________________________
00813 char *XrdCryptosslCipher::RefreshIV(int &l)
00814 {
00815    // Regenerate IV and return it
00816 
00817    // Generate a new IV
00818    GenerateIV();
00819 
00820    // Set output
00821    l = lIV;
00822    return fIV;
00823 }
00824 
00825 //____________________________________________________________________________
00826 void XrdCryptosslCipher::GenerateIV()
00827 {
00828    // Generate IV
00829 
00830    // Cleanup existing one, if any
00831    if (fIV) {
00832       delete[] fIV;
00833       fIV = 0;
00834       lIV = 0;
00835    }
00836 
00837    // Generate a new one
00838    fIV = XrdSutRndm::GetBuffer(EVP_MAX_IV_LENGTH);
00839    if (fIV)
00840       lIV = EVP_MAX_IV_LENGTH;
00841 }
00842 
00843 //____________________________________________________________________________
00844 int XrdCryptosslCipher::Encrypt(const char *in, int lin, char *out)
00845 {
00846    // Encrypt lin bytes at in with local cipher.
00847    // The outbut buffer must be provided by the caller for at least
00848    // EncOutLength(lin) bytes.
00849    // Returns number of meaningful bytes in out, or 0 in case of problems
00850 
00851    return EncDec(1, in, lin, out);
00852 }
00853 
00854 //____________________________________________________________________________
00855 int XrdCryptosslCipher::Decrypt(const char *in, int lin, char *out)
00856 {
00857    // Decrypt lin bytes at in with local cipher.
00858    // The outbut buffer must be provided by the caller for at least
00859    // DecOutLength(lin) bytes.
00860    // Returns number of meaningful bytes in out, or 0 in case of problems
00861 
00862    return EncDec(0, in, lin, out);
00863 }
00864 
00865 //____________________________________________________________________________
00866 int XrdCryptosslCipher::EncDec(int enc, const char *in, int lin, char *out)
00867 {
00868    // Encrypt (enc = 1)/ Decrypt (enc = 0) lin bytes at in with local cipher.
00869    // The outbut buffer must be provided by the caller for at least
00870    // EncOutLength(lin) or DecOutLength(lin) bytes.
00871    // Returns number of meaningful bytes in out, or 0 in case of problems
00872    EPNAME("Cipher::EncDec"); 
00873 
00874    int lout = 0;
00875 
00876    // Check inputs
00877    if (!in || lin <= 0 || !out) {
00878       DEBUG("wrong inputs arguments"); 
00879       if (!in) DEBUG("in: "<<in); 
00880       if (lin <= 0) DEBUG("lin: "<<lin); 
00881       if (!out) DEBUG("out: "<<out); 
00882       return 0;
00883    }
00884 
00885    // Set iv to the one in use
00886    unsigned char iv[EVP_MAX_IV_LENGTH];
00887    if (fIV) {
00888       memcpy((void *)iv,fIV,EVP_MAX_IV_LENGTH);
00889    } else {
00890       // We use 0's
00891       memset((void *)iv,0,EVP_MAX_IV_LENGTH);
00892    }
00893 
00894    // Action depend on the length of the key wrt default length
00895    if (deflength) {
00896       // Init ctx, set key (default length) and set IV
00897       if (!EVP_CipherInit(&ctx, cipher, (unsigned char *)Buffer(), iv, enc)) {
00898          DEBUG("error initializing"); 
00899          return 0;
00900       }
00901    } else {
00902       // Init ctx
00903       if (!EVP_CipherInit(&ctx, cipher, 0, 0, enc)) {
00904          DEBUG("error initializing - 1"); 
00905          return 0;
00906       }
00907       // Set key length
00908       EVP_CIPHER_CTX_set_key_length(&ctx,Length());
00909       // Set key and IV
00910       if (!EVP_CipherInit(&ctx, 0, (unsigned char *)Buffer(), iv, enc)) {
00911          DEBUG("error initializing - 2"); 
00912          return 0;
00913       }
00914    }
00915 
00916    // Encrypt / Decrypt
00917    int ltmp = 0;
00918    if (!EVP_CipherUpdate(&ctx, (unsigned char *)&out[0], &ltmp,
00919                                (unsigned char *)in, lin)) {
00920       DEBUG("error encrypting"); 
00921       return 0;
00922    }
00923    lout = ltmp;
00924    if (!EVP_CipherFinal(&ctx, (unsigned char *)&out[lout], &ltmp)) {
00925       DEBUG("error finalizing"); 
00926       return 0;
00927    }
00928 
00929    // Results
00930    lout += ltmp;
00931    return lout;
00932 }
00933 
00934 //____________________________________________________________________________
00935 int XrdCryptosslCipher::EncOutLength(int l)
00936 {
00937    // Required buffer size for encrypting l bytes
00938 
00939    return (l+EVP_CIPHER_CTX_block_size(&ctx));
00940 }
00941 
00942 //____________________________________________________________________________
00943 int XrdCryptosslCipher::DecOutLength(int l)
00944 {
00945    // Required buffer size for decrypting l bytes
00946 
00947    int lout = l+EVP_CIPHER_CTX_block_size(&ctx)+1;
00948    lout = (lout <= 0) ? l : lout;
00949    return lout;
00950 }

Generated on Tue Jul 5 14:46:33 2011 for ROOT_528-00b_version by  doxygen 1.5.1