XRootD
XrdCryptosslCipher Class Reference

#include <XrdCryptosslCipher.hh>

+ Inheritance diagram for XrdCryptosslCipher:
+ Collaboration diagram for XrdCryptosslCipher:

Public Member Functions

 XrdCryptosslCipher (bool padded, int len, char *pub, int lpub, const char *t)
 
 XrdCryptosslCipher (const char *t, int l, const char *k, int liv, const char *iv)
 
 XrdCryptosslCipher (const char *t, int l=0)
 
 XrdCryptosslCipher (const XrdCryptosslCipher &c)
 
 XrdCryptosslCipher (XrdSutBucket *b)
 
virtual ~XrdCryptosslCipher ()
 
XrdSutBucketAsBucket ()
 
void Cleanup ()
 
int DecOutLength (int l)
 
int Decrypt (const char *bin, int lin, char *out)
 
int EncOutLength (int l)
 
int Encrypt (const char *bin, int lin, char *out)
 
bool Finalize (bool padded, char *pub, int lpub, const char *t)
 
bool IsDefaultLength () const
 
bool IsValid ()
 
char * IV (int &l) const
 
int MaxIVLength () const
 
char * Public (int &lpub)
 
char * RefreshIV (int &l)
 
void SetIV (int l, const char *iv)
 
- Public Member Functions inherited from XrdCryptoCipher
 XrdCryptoCipher ()
 
virtual ~XrdCryptoCipher ()
 
int Decrypt (XrdSutBucket &buck, bool useiv=true)
 
int Encrypt (XrdSutBucket &buck, bool useiv=true)
 
bool Finalize (char *pub, int lpub, const char *t)
 
- Public Member Functions inherited from XrdCryptoBasic
 XrdCryptoBasic (const char *t=0, int l=0, const char *b=0)
 
virtual ~XrdCryptoBasic ()
 
char * AsHexString ()
 
virtual char * Buffer () const
 
virtual int FromHex (const char *hex)
 
virtual int Length () const
 
virtual int SetBuffer (int l, const char *b)
 
virtual int SetLength (int l)
 
virtual int SetType (const char *t)
 
virtual char * Type () const
 
virtual void UseBuffer (int l, const char *b)
 

Static Public Member Functions

static bool IsSupported (const char *cip)
 

Detailed Description

Definition at line 54 of file XrdCryptosslCipher.hh.

Constructor & Destructor Documentation

◆ XrdCryptosslCipher() [1/5]

XrdCryptosslCipher::XrdCryptosslCipher ( const char *  t,
int  l = 0 
)

Definition at line 223 of file XrdCryptosslCipher.cc.

224 {
225  // Main Constructor
226  // Complete initialization of a cipher of type t and length l
227  // The initialization vector is also created
228  // Used to create ciphers
229 
230  valid = 0;
231  ctx = 0;
232  fIV = 0;
233  lIV = 0;
234  cipher = 0;
235  fDH = 0;
236  deflength = 1;
237 
238  // Check and set type
239  char cipnam[64] = {"bf-cbc"};
240  if (t && strcmp(t,"default")) {
241  strcpy(cipnam,t);
242  cipnam[63] = 0;
243  }
244  cipher = EVP_get_cipherbyname(cipnam);
245 
246  if (cipher) {
247  // Determine key length
248  l = (l > EVP_MAX_KEY_LENGTH) ? EVP_MAX_KEY_LENGTH : l;
249  int ldef = EVP_CIPHER_key_length(cipher);
250  int lgen = (l > ldef) ? l : ldef;
251  // Generate and set a new key
252  char *ktmp = XrdSutRndm::GetBuffer(lgen);
253  if (ktmp) {
254  // Init context
255  ctx = EVP_CIPHER_CTX_new();
256  if (ctx) {
257  valid = 1;
258  // Try setting the key length
259  if (l && l != ldef) {
260  EVP_CipherInit_ex(ctx, cipher, 0, 0, 0, 1);
261  EVP_CIPHER_CTX_set_key_length(ctx,l);
262  EVP_CipherInit_ex(ctx, 0, 0, (unsigned char *)ktmp, 0, 1);
263  if (l == EVP_CIPHER_CTX_key_length(ctx)) {
264  // Use the l bytes at ktmp
265  SetBuffer(l,ktmp);
266  deflength = 0;
267  }
268  }
269  if (!Length()) {
270  EVP_CipherInit_ex(ctx, cipher, 0, (unsigned char *)ktmp, 0, 1);
271  SetBuffer(ldef,ktmp);
272  }
273  // Set also the type
274  SetType(cipnam);
275  }
276  // Cleanup
277  delete[] ktmp;
278  }
279  }
280 
281  // Finally, generate and set a new IV
282  if (valid)
283  GenerateIV();
284 }
virtual int SetBuffer(int l, const char *b)
virtual int Length() const
virtual int SetType(const char *t)
static char * GetBuffer(int len, int opt=-1)
Definition: XrdSutRndm.cc:179

References XrdSutRndm::GetBuffer(), XrdCryptoBasic::Length(), XrdCryptoBasic::SetBuffer(), and XrdCryptoBasic::SetType().

+ Here is the call graph for this function:

◆ XrdCryptosslCipher() [2/5]

XrdCryptosslCipher::XrdCryptosslCipher ( const char *  t,
int  l,
const char *  k,
int  liv,
const char *  iv 
)

Definition at line 287 of file XrdCryptosslCipher.cc.

289 {
290  // Constructor.
291  // Initialize a cipher of type t and length l using the key at k and
292  // the initialization vector at iv.
293  // Used to import ciphers.
294  valid = 0;
295  ctx = 0;
296  fIV = 0;
297  lIV = 0;
298  fDH = 0;
299  cipher = 0;
300  deflength = 1;
301 
302  // Check and set type
303  char cipnam[64] = {"bf-cbc"};
304  if (t && strcmp(t,"default")) {
305  strcpy(cipnam,t);
306  cipnam[63] = 0;
307  }
308  cipher = EVP_get_cipherbyname(cipnam);
309 
310  if (cipher) {
311  // Init context
312  ctx = EVP_CIPHER_CTX_new();
313  if (ctx) {
314  // Set the key
315  SetBuffer(l,k);
316  if (l != EVP_CIPHER_key_length(cipher))
317  deflength = 0;
318  // Set also the type
319  SetType(cipnam);
320  // Set validity flag
321  valid = 1;
322  }
323  }
324  //
325  // Init cipher
326  if (valid) {
327  //
328  // Set the IV
329  SetIV(liv,iv);
330 
331  if (deflength) {
332  EVP_CipherInit_ex(ctx, cipher, 0, (unsigned char *)Buffer(), 0, 1);
333  } else {
334  EVP_CipherInit_ex(ctx, cipher, 0, 0, 0, 1);
335  EVP_CIPHER_CTX_set_key_length(ctx,Length());
336  EVP_CipherInit_ex(ctx, 0, 0, (unsigned char *)Buffer(), 0, 1);
337  }
338  }
339 }
virtual char * Buffer() const
void SetIV(int l, const char *iv)

References XrdCryptoBasic::Buffer(), XrdCryptoBasic::Length(), XrdCryptoBasic::SetBuffer(), SetIV(), and XrdCryptoBasic::SetType().

+ Here is the call graph for this function:

◆ XrdCryptosslCipher() [3/5]

XrdCryptosslCipher::XrdCryptosslCipher ( XrdSutBucket b)

Definition at line 342 of file XrdCryptosslCipher.cc.

343 {
344  // Constructor from bucket.
345  // Initialize a cipher of type t and length l using the key at k
346  // Used to import ciphers.
347  valid = 0;
348  ctx = 0;
349  fIV = 0;
350  lIV = 0;
351  fDH = 0;
352  cipher = 0;
353  deflength = 1;
354 
355  if (bck && bck->size > 0) {
356 
357  valid = 1;
358 
359  kXR_int32 ltyp = 0;
360  kXR_int32 livc = 0;
361  kXR_int32 lbuf = 0;
362  kXR_int32 lp = 0;
363  kXR_int32 lg = 0;
364  kXR_int32 lpub = 0;
365  kXR_int32 lpri = 0;
366  char *bp = bck->buffer;
367  int cur = 0;
368  memcpy(&ltyp,bp+cur,sizeof(kXR_int32));
369  cur += sizeof(kXR_int32);
370  memcpy(&livc,bp+cur,sizeof(kXR_int32));
371  cur += sizeof(kXR_int32);
372  memcpy(&lbuf,bp+cur,sizeof(kXR_int32));
373  cur += sizeof(kXR_int32);
374  memcpy(&lp,bp+cur,sizeof(kXR_int32));
375  cur += sizeof(kXR_int32);
376  memcpy(&lg,bp+cur,sizeof(kXR_int32));
377  cur += sizeof(kXR_int32);
378  memcpy(&lpub,bp+cur,sizeof(kXR_int32));
379  cur += sizeof(kXR_int32);
380  memcpy(&lpri,bp+cur,sizeof(kXR_int32));
381  cur += sizeof(kXR_int32);
382  // Type
383  if (ltyp) {
384  char *buf = new char[ltyp+1];
385  if (buf) {
386  memcpy(buf,bp+cur,ltyp);
387  buf[ltyp] = 0;
388  cipher = EVP_get_cipherbyname(buf);
389  if (!cipher)
390  cipher = EVP_get_cipherbyname("bf-cbc");
391  if (cipher) {
392  // Set the type
393  SetType(buf);
394  } else {
395  valid = 0;
396  }
397  delete[] buf;
398  } else
399  valid = 0;
400  cur += ltyp;
401  }
402  // IV
403  if (livc) {
404  char *buf = new char[livc];
405  if (buf) {
406  memcpy(buf,bp+cur,livc);
407  cur += livc;
408  // Set the IV
409  SetIV(livc,buf);
410  delete[] buf;
411  } else
412  valid = 0;
413  cur += livc;
414  }
415  // buffer
416  if (lbuf) {
417  char *buf = new char[lbuf];
418  if (buf) {
419  memcpy(buf,bp+cur,lbuf);
420  // Set the buffer
421  UseBuffer(lbuf,buf);
422  if (cipher && lbuf != EVP_CIPHER_key_length(cipher))
423  deflength = 0;
424  } else
425  valid = 0;
426  cur += lbuf;
427  }
428  // DH, if any
429  if (lp > 0 || lg > 0 || lpub > 0 || lpri > 0) {
430  char *buf = 0;
431  BIGNUM *p = NULL, *g = NULL;
432  BIGNUM *pub = NULL, *pri = NULL;
433  // p
434  if (lp > 0) {
435  buf = new char[lp+1];
436  if (buf) {
437  memcpy(buf,bp+cur,lp);
438  buf[lp] = 0;
439  BN_hex2bn(&p,buf);
440  delete[] buf;
441  } else
442  valid = 0;
443  cur += lp;
444  }
445  // g
446  if (lg > 0) {
447  buf = new char[lg+1];
448  if (buf) {
449  memcpy(buf,bp+cur,lg);
450  buf[lg] = 0;
451  BN_hex2bn(&g,buf);
452  delete[] buf;
453  } else
454  valid = 0;
455  cur += lg;
456  }
457  // pub_key
458  if (lpub > 0) {
459  buf = new char[lpub+1];
460  if (buf) {
461  memcpy(buf,bp+cur,lpub);
462  buf[lpub] = 0;
463  BN_hex2bn(&pub,buf);
464  delete[] buf;
465  } else
466  valid = 0;
467  cur += lpub;
468  }
469  // priv_key
470  if (lpri > 0) {
471  buf = new char[lpri+1];
472  if (buf) {
473  memcpy(buf,bp+cur,lpri);
474  buf[lpri] = 0;
475  BN_hex2bn(&pri,buf);
476  delete[] buf;
477  } else
478  valid = 0;
479  cur += lpri;
480  }
481 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
482  OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
483  if (p) OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p);
484  if (g) OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g);
485  if (pub) OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub);
486  if (pri) OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, pri);
487  OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld);
488  OSSL_PARAM_BLD_free(bld);
489  if (p) BN_free(p);
490  if (g) BN_free(g);
491  if (pub) BN_free(pub);
492  if (pri) BN_free(pri);
493  EVP_PKEY_CTX *pkctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, 0);
494  EVP_PKEY_fromdata_init(pkctx);
495  EVP_PKEY_fromdata(pkctx, &fDH, EVP_PKEY_KEYPAIR, params);
496  EVP_PKEY_CTX_free(pkctx);
497  OSSL_PARAM_free(params);
498 #else
499  DH* dh = DH_new();
500  DH_set0_pqg(dh, p, NULL, g);
501  DH_set0_key(dh, pub, pri);
502  fDH = EVP_PKEY_new();
503  EVP_PKEY_assign_DH(fDH, dh);
504 #endif
505  if (XrdCheckDH(fDH) != 1)
506  valid = 0;
507  }
508  }
509  //
510  // Init cipher
511  if (valid) {
512  // Init context
513  ctx = EVP_CIPHER_CTX_new();
514  if (ctx) {
515  if (deflength) {
516  EVP_CipherInit_ex(ctx, cipher, 0, (unsigned char *)Buffer(), 0, 1);
517  } else {
518  EVP_CipherInit_ex(ctx, cipher, 0, 0, 0, 1);
519  EVP_CIPHER_CTX_set_key_length(ctx,Length());
520  EVP_CipherInit_ex(ctx, 0, 0, (unsigned char *)Buffer(), 0, 1);
521  }
522  } else
523  valid = 0;
524  }
525  if (!valid) {
526  Cleanup();
527  }
528 }
int kXR_int32
Definition: XPtypes.hh:89
static int XrdCheckDH(EVP_PKEY *pkey)
static int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
static int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
virtual void UseBuffer(int l, const char *b)

References XrdCryptoBasic::Buffer(), XrdSutBucket::buffer, Cleanup(), DH_set0_key(), DH_set0_pqg(), XrdCryptoBasic::Length(), SetIV(), XrdCryptoBasic::SetType(), XrdSutBucket::size, XrdCryptoBasic::UseBuffer(), and XrdCheckDH().

+ Here is the call graph for this function:

◆ XrdCryptosslCipher() [4/5]

XrdCryptosslCipher::XrdCryptosslCipher ( bool  padded,
int  len,
char *  pub,
int  lpub,
const char *  t 
)

Definition at line 531 of file XrdCryptosslCipher.cc.

533 {
534  // Constructor for key agreement.
535  // If pub is not defined, generates a DH full key,
536  // the public part and parameters can be retrieved using Public().
537  // 'bits' is ignored (DH key is generated once)
538  // If pub is defined with the public part and parameters of the
539  // counterpart fully initialize a cipher with that information.
540  // Sets also the name to 't', if different from the default one.
541  // Used for key agreement.
542  EPNAME("sslCipher::XrdCryptosslCipher");
543 
544  valid = 0;
545  ctx = 0;
546  fIV = 0;
547  lIV = 0;
548  fDH = 0;
549  cipher = 0;
550  deflength = 1;
551 
552  if (!pub) {
553 
554  DEBUG("generate DH parameters");
555  EVP_PKEY *dhparms = getFixedDHParams();
556 //
557 // Important historical context:
558 // - We used to generate DH params on every server startup (commented
559 // out below). This was prohibitively costly to do on startup for
560 // DH parameters large enough to be considered secure.
561 // - OpenSSL 3.0 improved the DH parameter generation to avoid leaking
562 // the first bit of the session key (see https://github.com/openssl/openssl/issues/9792
563 // for more information). However, a side-effect is that the new
564 // parameters are not recognized as valid in OpenSSL 1.0.2.
565 // - Since we can't control old client versions and new servers can't
566 // generate compatible DH parameters, we switch to a fixed, much stronger
567 // set of DH parameters (3072 bits).
568 //
569 // The impact is that we continue leaking the first bit of the session key
570 // (meaning it's effectively 127 bits not 128 bits -- still plenty secure)
571 // but upgrade the DH parameters to something more modern (3072; previously,
572 // it was 512 bits which was not considered secure). The downside
573 // of fixed DH parameters is that if a nation-state attacked our selected
574 // parameters (using technology not currently available), we would have
575 // to upgrade all servers with a new set of DH parameters.
576 //
577 
578 /*
579  EVP_PKEY_CTX *pkctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, 0);
580  EVP_PKEY_paramgen_init(pkctx);
581  EVP_PKEY_CTX_set_dh_paramgen_prime_len(pkctx, kDHMINBITS);
582  EVP_PKEY_CTX_set_dh_paramgen_generator(pkctx, 5);
583  EVP_PKEY_paramgen(pkctx, &dhParam);
584  EVP_PKEY_CTX_free(pkctx);
585 */
586 
587  DEBUG("configure DH parameters");
588  //
589  // Set params for DH object
590  EVP_PKEY_CTX *pkctx = EVP_PKEY_CTX_new(dhparms, 0);
591  EVP_PKEY_keygen_init(pkctx);
592  EVP_PKEY_keygen(pkctx, &fDH);
593  EVP_PKEY_CTX_free(pkctx);
594  if (fDH) {
595  // Init context
596  ctx = EVP_CIPHER_CTX_new();
597  if (ctx)
598  valid = 1;
599  }
600 
601  } else {
602  DEBUG("initialize cipher from key-agreement buffer");
603  //
604  char *ktmp = 0;
605  size_t ltmp = 0;
606  // Extract string with bignumber
607  BIGNUM *bnpub = 0;
608  char *pb = strstr(pub,"---BPUB---");
609  char *pe = strstr(pub,"---EPUB--"); // one less (pub not null-terminated)
610  if (pb && pe) {
611  lpub = (int)(pb-pub);
612  pb += 10;
613  *pe = 0;
614  BN_hex2bn(&bnpub, pb);
615  *pe = '-';
616  }
617  if (bnpub) {
618  //
619  // Prepare to decode the input buffer
620  BIO *biop = BIO_new(BIO_s_mem());
621  if (biop) {
622  //
623  // Write buffer into BIO
624  BIO_write(biop,pub,lpub);
625  //
626  // Read params from BIO
627  EVP_PKEY *dhParam = 0;
628  PEM_read_bio_Parameters(biop, &dhParam);
629  if (dhParam) {
630  if (XrdCheckDH(dhParam) == 1) {
631  //
632  // generate DH key
633  EVP_PKEY_CTX *pkctx = EVP_PKEY_CTX_new(dhParam, 0);
634  EVP_PKEY_keygen_init(pkctx);
635  EVP_PKEY_keygen(pkctx, &fDH);
636  EVP_PKEY_CTX_free(pkctx);
637  if (fDH) {
638  // Now we can compute the cipher
639  ltmp = EVP_PKEY_size(fDH);
640  ktmp = new char[ltmp];
641  memset(ktmp, 0, ltmp);
642  if (ktmp) {
643  // Create peer public key
644 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
645  EVP_PKEY *peer = 0;
646  OSSL_PARAM *params1 = 0;
647  EVP_PKEY_todata( dhParam, EVP_PKEY_KEY_PARAMETERS, &params1 );
648  OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
649  OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, bnpub);
650  OSSL_PARAM *params2 = OSSL_PARAM_BLD_to_param(bld);
651  OSSL_PARAM_BLD_free(bld);
652  OSSL_PARAM *params = OSSL_PARAM_merge( params1, params2 );
653  pkctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, 0);
654  EVP_PKEY_fromdata_init(pkctx);
655  EVP_PKEY_fromdata(pkctx, &peer, EVP_PKEY_KEYPAIR, params);
656  EVP_PKEY_CTX_free(pkctx);
657  OSSL_PARAM_free(params);
658  OSSL_PARAM_free(params1);
659  OSSL_PARAM_free(params2);
660 #else
661  DH* dh = DH_new();
662  DH_set0_key(dh, BN_dup(bnpub), NULL);
663  EVP_PKEY *peer = EVP_PKEY_new();
664  EVP_PKEY_assign_DH(peer, dh);
665 #endif
666  // Derive shared secret
667  pkctx = EVP_PKEY_CTX_new(fDH, 0);
668  EVP_PKEY_derive_init(pkctx);
669 #if OPENSSL_VERSION_NUMBER >= 0x10101000L
670  EVP_PKEY_CTX_set_dh_pad(pkctx, padded);
671 #endif
672  EVP_PKEY_derive_set_peer(pkctx, peer);
673  EVP_PKEY_derive(pkctx, (unsigned char *)ktmp, &ltmp);
674  EVP_PKEY_CTX_free(pkctx);
675  EVP_PKEY_free(peer);
676  if (ltmp > 0) {
677 #if OPENSSL_VERSION_NUMBER < 0x10101000L
678  if (padded) {
679  int pad = EVP_PKEY_size(fDH) - ltmp;
680  if (pad > 0) {
681  memmove(ktmp + pad, ktmp, ltmp);
682  memset(ktmp, 0, pad);
683  ltmp += pad;
684  }
685  }
686 #endif
687  valid = 1;
688  }
689  }
690  }
691  }
692  EVP_PKEY_free(dhParam);
693  }
694  BIO_free(biop);
695  }
696  BN_free( bnpub );
697  }
698  //
699  // If a valid key has been computed, set the cipher
700  if (valid) {
701  // Init context
702  ctx = EVP_CIPHER_CTX_new();
703  if (ctx) {
704  // Check and set type
705  char cipnam[64] = {"bf-cbc"};
706  if (t && strcmp(t,"default")) {
707  strcpy(cipnam,t);
708  cipnam[63] = 0;
709  }
710  if ((cipher = EVP_get_cipherbyname(cipnam))) {
711  // At most EVP_MAX_KEY_LENGTH bytes
712  ltmp = (ltmp > EVP_MAX_KEY_LENGTH) ? EVP_MAX_KEY_LENGTH : ltmp;
713  int ldef = EVP_CIPHER_key_length(cipher);
714  // Try setting the key length
715  if ((int)ltmp != ldef) {
716  EVP_CipherInit_ex(ctx, cipher, 0, 0, 0, 1);
717  EVP_CIPHER_CTX_set_key_length(ctx,ltmp);
718  EVP_CipherInit_ex(ctx, 0, 0, (unsigned char *)ktmp, 0, 1);
719  if ((int)ltmp == EVP_CIPHER_CTX_key_length(ctx)) {
720  // Use the ltmp bytes at ktmp
721  SetBuffer(ltmp,ktmp);
722  deflength = 0;
723  }
724  }
725  if (!Length()) {
726  EVP_CipherInit_ex(ctx, cipher, 0, (unsigned char *)ktmp, 0, 1);
727  SetBuffer(ldef,ktmp);
728  }
729  // Set also the type
730  SetType(cipnam);
731  }
732  } else
733  valid = 0;
734  }
735  // Cleanup
736  if (ktmp) {delete[] ktmp; ktmp = 0;}
737  }
738 
739  // Cleanup, if invalid
740  if (!valid)
741  Cleanup();
742 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
static EVP_PKEY * getFixedDHParams()

References Cleanup(), DEBUG, DH_set0_key(), EPNAME, getFixedDHParams(), XrdCryptoBasic::Length(), XrdCryptoBasic::SetBuffer(), XrdCryptoBasic::SetType(), and XrdCheckDH().

+ Here is the call graph for this function:

◆ XrdCryptosslCipher() [5/5]

XrdCryptosslCipher::XrdCryptosslCipher ( const XrdCryptosslCipher c)

Definition at line 745 of file XrdCryptosslCipher.cc.

746  : XrdCryptoCipher()
747 {
748  // Copy Constructor
749 
750  // Basics
751  deflength = c.deflength;
752  valid = c.valid;
753  ctx = 0;
754  // IV
755  lIV = 0;
756  fIV = 0;
757  SetIV(c.lIV,c.fIV);
758 
759  // Cipher
760  cipher = c.cipher;
761  // Set the key
762  SetBuffer(c.Length(),c.Buffer());
763  // Set also the type
764  SetType(c.Type());
765  // DH
766  fDH = 0;
767  if (valid && c.fDH) {
768  valid = 0;
769 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
770  BIGNUM *p = BN_new();
771  BIGNUM *g = BN_new();
772  BIGNUM *pub = BN_new();
773  BIGNUM *pri = BN_new();
774  OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
775  if (EVP_PKEY_get_bn_param(c.fDH, OSSL_PKEY_PARAM_FFC_P, &p) == 1)
776  OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p);
777  if (EVP_PKEY_get_bn_param(c.fDH, OSSL_PKEY_PARAM_FFC_G, &g) == 1)
778  OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g);
779  if (EVP_PKEY_get_bn_param(c.fDH, OSSL_PKEY_PARAM_PUB_KEY, &pub) == 1)
780  OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub);
781  if (EVP_PKEY_get_bn_param(c.fDH, OSSL_PKEY_PARAM_PRIV_KEY, &pri) == 1)
782  OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, pri);
783  OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld);
784  OSSL_PARAM_BLD_free(bld);
785  BN_free(p);
786  BN_free(g);
787  BN_free(pub);
788  BN_free(pri);
789  EVP_PKEY_CTX *pkctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, 0);
790  EVP_PKEY_fromdata_init(pkctx);
791  EVP_PKEY_fromdata(pkctx, &fDH, EVP_PKEY_KEYPAIR, params);
792  EVP_PKEY_CTX_free(pkctx);
793  OSSL_PARAM_free(params);
794 #else
795  DH* dh = DH_new();
796  if (dh) {
797  const BIGNUM *p, *g;
798  DH_get0_pqg(EVP_PKEY_get0_DH(c.fDH), &p, NULL, &g);
799  DH_set0_pqg(dh, p ? BN_dup(p) : NULL, NULL, g ? BN_dup(g) : NULL);
800  const BIGNUM *pub, *pri;
801  DH_get0_key(EVP_PKEY_get0_DH(c.fDH), &pub, &pri);
802  DH_set0_key(dh, pub ? BN_dup(pub) : NULL, pri ? BN_dup(pri) : NULL);
803  fDH = EVP_PKEY_new();
804  EVP_PKEY_assign_DH(fDH, dh);
805  }
806 #endif
807  if (fDH) {
808  if (XrdCheckDH(fDH) == 1)
809  valid = 1;
810  }
811  }
812  if (valid) {
813  // Init context
814  ctx = EVP_CIPHER_CTX_new();
815  if (!ctx)
816  valid = 0;
817  }
818  if (!valid) {
819  Cleanup();
820  }
821 }
static DH * EVP_PKEY_get0_DH(EVP_PKEY *pkey)
static void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
static void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
virtual char * Type() const

References XrdCryptoBasic::Buffer(), Cleanup(), DH_get0_key(), DH_get0_pqg(), DH_set0_key(), DH_set0_pqg(), EVP_PKEY_get0_DH(), XrdCryptoBasic::Length(), XrdCryptoBasic::SetBuffer(), SetIV(), XrdCryptoBasic::SetType(), XrdCryptoBasic::Type(), and XrdCheckDH().

+ Here is the call graph for this function:

◆ ~XrdCryptosslCipher()

XrdCryptosslCipher::~XrdCryptosslCipher ( )
virtual

Definition at line 824 of file XrdCryptosslCipher.cc.

825 {
826  // Destructor.
827 
828  // Cleanup IV
829  if (fIV)
830  delete[] fIV;
831 
832  // Cleanups
833  if (valid)
834  EVP_CIPHER_CTX_free(ctx);
835  Cleanup();
836 }

References Cleanup().

+ Here is the call graph for this function:

Member Function Documentation

◆ AsBucket()

XrdSutBucket * XrdCryptosslCipher::AsBucket ( )
virtual

Reimplemented from XrdCryptoCipher.

Definition at line 1116 of file XrdCryptosslCipher.cc.

1117 {
1118  // Return pointer to a bucket created using the internal information
1119  // serialized
1120  // The bucket is responsible for the allocated memory
1121 
1122  XrdSutBucket *buck = (XrdSutBucket *)0;
1123 
1124  if (valid) {
1125 
1126  // Serialize .. total length
1127  kXR_int32 lbuf = Length();
1128  kXR_int32 ltyp = Type() ? strlen(Type()) : 0;
1129  kXR_int32 livc = lIV;
1130 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1131  BIGNUM *p = BN_new();
1132  BIGNUM *g = BN_new();
1133  BIGNUM *pub = BN_new();
1134  BIGNUM *pri = BN_new();
1135  EVP_PKEY_get_bn_param(fDH, OSSL_PKEY_PARAM_FFC_P, &p);
1136  EVP_PKEY_get_bn_param(fDH, OSSL_PKEY_PARAM_FFC_G, &g);
1137  EVP_PKEY_get_bn_param(fDH, OSSL_PKEY_PARAM_PUB_KEY, &pub);
1138  EVP_PKEY_get_bn_param(fDH, OSSL_PKEY_PARAM_PRIV_KEY, &pri);
1139 #else
1140  const BIGNUM *p, *g;
1141  const BIGNUM *pub, *pri;
1142  DH_get0_pqg(EVP_PKEY_get0_DH(fDH), &p, NULL, &g);
1143  DH_get0_key(EVP_PKEY_get0_DH(fDH), &pub, &pri);
1144 #endif
1145  char *cp = BN_bn2hex(p);
1146  char *cg = BN_bn2hex(g);
1147  char *cpub = BN_bn2hex(pub);
1148  char *cpri = BN_bn2hex(pri);
1149 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1150  BN_free(p);
1151  BN_free(g);
1152  BN_free(pub);
1153  BN_free(pri);
1154 #endif
1155  kXR_int32 lp = cp ? strlen(cp) : 0;
1156  kXR_int32 lg = cg ? strlen(cg) : 0;
1157  kXR_int32 lpub = cpub ? strlen(cpub) : 0;
1158  kXR_int32 lpri = cpri ? strlen(cpri) : 0;
1159  int ltot = 7*sizeof(kXR_int32) + ltyp + Length() + livc +
1160  lp + lg + lpub + lpri;
1161  char *newbuf = new char[ltot];
1162  if (newbuf) {
1163  int cur = 0;
1164  memcpy(newbuf+cur,&ltyp,sizeof(kXR_int32));
1165  cur += sizeof(kXR_int32);
1166  memcpy(newbuf+cur,&livc,sizeof(kXR_int32));
1167  cur += sizeof(kXR_int32);
1168  memcpy(newbuf+cur,&lbuf,sizeof(kXR_int32));
1169  cur += sizeof(kXR_int32);
1170  memcpy(newbuf+cur,&lp,sizeof(kXR_int32));
1171  cur += sizeof(kXR_int32);
1172  memcpy(newbuf+cur,&lg,sizeof(kXR_int32));
1173  cur += sizeof(kXR_int32);
1174  memcpy(newbuf+cur,&lpub,sizeof(kXR_int32));
1175  cur += sizeof(kXR_int32);
1176  memcpy(newbuf+cur,&lpri,sizeof(kXR_int32));
1177  cur += sizeof(kXR_int32);
1178  if (Type()) {
1179  memcpy(newbuf+cur,Type(),ltyp);
1180  cur += ltyp;
1181  }
1182  if (fIV) {
1183  memcpy(newbuf+cur,fIV,livc);
1184  cur += livc;
1185  }
1186  if (Buffer()) {
1187  memcpy(newbuf+cur,Buffer(),lbuf);
1188  cur += lbuf;
1189  }
1190  if (cp) {
1191  memcpy(newbuf+cur,cp,lp);
1192  cur += lp;
1193  OPENSSL_free(cp);
1194  }
1195  if (cg) {
1196  memcpy(newbuf+cur,cg,lg);
1197  cur += lg;
1198  OPENSSL_free(cg);
1199  }
1200  if (cpub) {
1201  memcpy(newbuf+cur,cpub,lpub);
1202  cur += lpub;
1203  OPENSSL_free(cpub);
1204  }
1205  if (cpri) {
1206  memcpy(newbuf+cur,cpri,lpri);
1207  cur += lpri;
1208  OPENSSL_free(cpri);
1209  }
1210  // The bucket now
1211  buck = new XrdSutBucket(newbuf,ltot,kXRS_cipher);
1212  }
1213  }
1214 
1215  return buck;
1216 }
@ kXRS_cipher
Definition: XrdSutAux.hh:62

References XrdCryptoBasic::Buffer(), DH_get0_key(), DH_get0_pqg(), EVP_PKEY_get0_DH(), kXRS_cipher, XrdCryptoBasic::Length(), and XrdCryptoBasic::Type().

+ Here is the call graph for this function:

◆ Cleanup()

void XrdCryptosslCipher::Cleanup ( )

Definition at line 839 of file XrdCryptosslCipher.cc.

840 {
841  // Cleanup temporary memory
842 
843  // Cleanup IV
844  if (fDH) {
845  EVP_PKEY_free(fDH);
846  fDH = 0;
847  }
848 }

Referenced by XrdCryptosslCipher(), ~XrdCryptosslCipher(), and Finalize().

+ Here is the caller graph for this function:

◆ DecOutLength()

int XrdCryptosslCipher::DecOutLength ( int  l)
virtual

Reimplemented from XrdCryptoCipher.

Definition at line 1371 of file XrdCryptosslCipher.cc.

1372 {
1373  // Required buffer size for decrypting l bytes
1374 
1375  int lout = l+EVP_CIPHER_CTX_block_size(ctx)+1;
1376  lout = (lout <= 0) ? l : lout;
1377  return lout;
1378 }

◆ Decrypt()

int XrdCryptosslCipher::Decrypt ( const char *  bin,
int  lin,
char *  out 
)
virtual

Reimplemented from XrdCryptoCipher.

Definition at line 1281 of file XrdCryptosslCipher.cc.

1282 {
1283  // Decrypt lin bytes at in with local cipher.
1284  // The outbut buffer must be provided by the caller for at least
1285  // DecOutLength(lin) bytes.
1286  // Returns number of meaningful bytes in out, or 0 in case of problems
1287 
1288  return EncDec(0, in, lin, out);
1289 }

◆ EncOutLength()

int XrdCryptosslCipher::EncOutLength ( int  l)
virtual

Reimplemented from XrdCryptoCipher.

Definition at line 1363 of file XrdCryptosslCipher.cc.

1364 {
1365  // Required buffer size for encrypting l bytes
1366 
1367  return (l+EVP_CIPHER_CTX_block_size(ctx));
1368 }

◆ Encrypt()

int XrdCryptosslCipher::Encrypt ( const char *  bin,
int  lin,
char *  out 
)
virtual

Reimplemented from XrdCryptoCipher.

Definition at line 1270 of file XrdCryptosslCipher.cc.

1271 {
1272  // Encrypt lin bytes at in with local cipher.
1273  // The outbut buffer must be provided by the caller for at least
1274  // EncOutLength(lin) bytes.
1275  // Returns number of meaningful bytes in out, or 0 in case of problems
1276 
1277  return EncDec(1, in, lin, out);
1278 }

◆ Finalize()

bool XrdCryptosslCipher::Finalize ( bool  padded,
char *  pub,
int  lpub,
const char *  t 
)
virtual

Reimplemented from XrdCryptoCipher.

Definition at line 851 of file XrdCryptosslCipher.cc.

853 {
854  // Finalize cipher during key agreement. Should be called
855  // for a cipher build with special constructor defining member fDH.
856  // The buffer pub should contain the public part of the counterpart.
857  // Sets also the name to 't', if different from the default one.
858  // Used for key agreement.
859  EPNAME("sslCipher::Finalize");
860 
861  if (!fDH) {
862  DEBUG("DH undefined: this cipher cannot be finalized"
863  " by this method");
864  return 0;
865  }
866 
867  char *ktmp = 0;
868  size_t ltmp = 0;
869  valid = 0;
870  if (pub) {
871  //
872  // Extract string with bignumber
873  BIGNUM *bnpub = 0;
874  char *pb = static_cast<char*>(memmem(pub, lpub, "---BPUB---", 10));
875  char *pe = static_cast<char*>(memmem(pub, lpub, "---EPUB--", 9));
876  if (pb && pe) {
877  //lpub = (int)(pb-pub);
878  pb += 10;
879  *pe = 0;
880  BN_hex2bn(&bnpub, pb);
881  *pe = '-';
882  }
883  if (bnpub) {
884  // Now we can compute the cipher
885  ltmp = EVP_PKEY_size(fDH);
886  ktmp = new char[ltmp];
887  if (ktmp) {
888  memset(ktmp, 0, ltmp);
889  // Create peer public key
890  EVP_PKEY_CTX *pkctx;
891 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
892  EVP_PKEY *peer = nullptr;
893  OSSL_PARAM *params1 = nullptr;
894  EVP_PKEY_todata(fDH, EVP_PKEY_KEY_PARAMETERS, &params1);
895  OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
896  OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, bnpub);
897  OSSL_PARAM *params2 = OSSL_PARAM_BLD_to_param(bld);
898  OSSL_PARAM_BLD_free(bld);
899  OSSL_PARAM *params = OSSL_PARAM_merge(params1, params2);
900  pkctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, 0);
901  EVP_PKEY_fromdata_init(pkctx);
902  EVP_PKEY_fromdata(pkctx, &peer, EVP_PKEY_PUBLIC_KEY, params);
903  OSSL_PARAM_free(params1);
904  OSSL_PARAM_free(params2);
905  OSSL_PARAM_free(params);
906  EVP_PKEY_CTX_free(pkctx);
907 #else
908  DH* dh = DH_new();
909  DH_set0_key(dh, BN_dup(bnpub), NULL);
910  EVP_PKEY *peer = EVP_PKEY_new();
911  EVP_PKEY_assign_DH(peer, dh);
912 #endif
913  // Derive shared secret
914  pkctx = EVP_PKEY_CTX_new(fDH, 0);
915  EVP_PKEY_derive_init(pkctx);
916 #if OPENSSL_VERSION_NUMBER >= 0x10101000L
917  EVP_PKEY_CTX_set_dh_pad(pkctx, padded);
918 #endif
919  EVP_PKEY_derive_set_peer(pkctx, peer);
920  EVP_PKEY_derive(pkctx, (unsigned char *)ktmp, &ltmp);
921  EVP_PKEY_CTX_free(pkctx);
922  EVP_PKEY_free(peer);
923  if (ltmp > 0) {
924 #if OPENSSL_VERSION_NUMBER < 0x10101000L
925  if (padded) {
926  int pad = EVP_PKEY_size(fDH) - ltmp;
927  if (pad > 0) {
928  memmove(ktmp + pad, ktmp, ltmp);
929  memset(ktmp, 0, pad);
930  ltmp += pad;
931  }
932  }
933 #endif
934  valid = 1;
935  }
936  }
937  BN_free(bnpub);
938  bnpub=0;
939  }
940  //
941  // If a valid key has been computed, set the cipher
942  if (valid) {
943  // Check and set type
944  char cipnam[64] = {"bf-cbc"};
945  if (t && strcmp(t,"default")) {
946  strcpy(cipnam,t);
947  cipnam[63] = 0;
948  }
949  if ((cipher = EVP_get_cipherbyname(cipnam))) {
950  // At most EVP_MAX_KEY_LENGTH bytes
951  ltmp = (ltmp > EVP_MAX_KEY_LENGTH) ? EVP_MAX_KEY_LENGTH : ltmp;
952  int ldef = EVP_CIPHER_key_length(cipher);
953  // Try setting the key length
954  if ((int)ltmp != ldef) {
955  EVP_CipherInit_ex(ctx, cipher, 0, 0, 0, 1);
956  EVP_CIPHER_CTX_set_key_length(ctx,ltmp);
957  EVP_CipherInit_ex(ctx, 0, 0, (unsigned char *)ktmp, 0, 1);
958  if ((int)ltmp == EVP_CIPHER_CTX_key_length(ctx)) {
959  // Use the ltmp bytes at ktmp
960  SetBuffer(ltmp,ktmp);
961  deflength = 0;
962  }
963  }
964  if (!Length()) {
965  EVP_CipherInit_ex(ctx, cipher, 0, (unsigned char *)ktmp, 0, 1);
966  SetBuffer(ldef,ktmp);
967  }
968  // Set also the type
969  SetType(cipnam);
970  }
971  }
972  // Cleanup
973  if (ktmp) {delete[] ktmp; ktmp = 0;}
974  }
975 
976  // Cleanup, if invalid
977  if (!valid) {
978  EVP_CIPHER_CTX_free(ctx);
979  Cleanup();
980  }
981 
982  // We are done
983  return valid;
984 }

References Cleanup(), DEBUG, DH_set0_key(), EPNAME, XrdCryptoBasic::Length(), XrdCryptoBasic::SetBuffer(), and XrdCryptoBasic::SetType().

+ Here is the call graph for this function:

◆ IsDefaultLength()

bool XrdCryptosslCipher::IsDefaultLength ( ) const
inlinevirtual

Reimplemented from XrdCryptoCipher.

Definition at line 97 of file XrdCryptosslCipher.hh.

97 { return deflength; }

◆ IsSupported()

bool XrdCryptosslCipher::IsSupported ( const char *  cip)
static

Definition at line 215 of file XrdCryptosslCipher.cc.

216 {
217  // Check if the specified cipher is supported
218 
219  return (EVP_get_cipherbyname(cip) != 0);
220 }

Referenced by XrdCryptosslFactory::SupportedCipher().

+ Here is the caller graph for this function:

◆ IsValid()

bool XrdCryptosslCipher::IsValid ( )
inlinevirtual

Reimplemented from XrdCryptoCipher.

Definition at line 84 of file XrdCryptosslCipher.hh.

84 { return valid; }

◆ IV()

char* XrdCryptosslCipher::IV ( int &  l) const
inlinevirtual

Reimplemented from XrdCryptoCipher.

Definition at line 96 of file XrdCryptosslCipher.hh.

96 { l = lIV; return fIV; }

◆ MaxIVLength()

int XrdCryptosslCipher::MaxIVLength ( ) const
virtual

Reimplemented from XrdCryptoCipher.

Definition at line 1381 of file XrdCryptosslCipher.cc.

1382 {
1383  // Return the max cipher IV length
1384 
1385  return (lIV > 0) ? lIV : EVP_MAX_IV_LENGTH;
1386 }

◆ Public()

char * XrdCryptosslCipher::Public ( int &  lpub)
virtual

Reimplemented from XrdCryptoCipher.

Definition at line 1005 of file XrdCryptosslCipher.cc.

1006 {
1007  // Return buffer with the public part of the DH key and the shared
1008  // parameters; lpub contains the length of the meaningful bytes.
1009  // Buffer should be deleted by the caller.
1010  static int lhend = strlen("-----END DH PARAMETERS-----");
1011 
1012  if (fDH) {
1013  //
1014  // Calculate and write public key hex
1015 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1016  BIGNUM *pub = BN_new();
1017  EVP_PKEY_get_bn_param(fDH, OSSL_PKEY_PARAM_PUB_KEY, &pub);
1018  char *phex = BN_bn2hex(pub);
1019  BN_free(pub);
1020 #else
1021  const BIGNUM *pub;
1022  DH_get0_key(EVP_PKEY_get0_DH(fDH), &pub, NULL);
1023  char *phex = BN_bn2hex(pub);
1024 #endif
1025  int lhex = strlen(phex);
1026  //
1027  // Prepare bio to export info buffer
1028  BIO *biop = BIO_new(BIO_s_mem());
1029  if (biop) {
1030  int ltmp = Publen() + lhex + 20;
1031  char *pub = new char[ltmp];
1032  if (pub) {
1033  // Write parms first
1034  PEM_write_bio_Parameters(biop, fDH);
1035  // Read key from BIO to buf
1036  BIO_read(biop,(void *)pub,ltmp);
1037  BIO_free(biop);
1038  // Add public key
1039  char *p = strstr(pub,"-----END DH PARAMETERS-----");
1040  // Buffer length up to now
1041  lpub = (int)(p - pub) + lhend + 1;
1042  if (phex && p) {
1043  // position at the end
1044  p += (lhend+1);
1045  // Begin of public key hex
1046  memcpy(p,"---BPUB---",10);
1047  p += 10;
1048  // Calculate and write public key hex
1049  memcpy(p,phex,lhex);
1050  OPENSSL_free(phex);
1051  // End of public key hex
1052  p += lhex;
1053  memcpy(p,"---EPUB---",10);
1054  // Calculate total length
1055  lpub += (20 + lhex);
1056  } else {
1057  if (phex) OPENSSL_free(phex);
1058  }
1059  // return
1060  return pub;
1061  }
1062  } else {
1063  if (phex) OPENSSL_free(phex);
1064  }
1065  }
1066 
1067  lpub = 0;
1068  return (char *)0;
1069 }

References DH_get0_key(), and EVP_PKEY_get0_DH().

+ Here is the call graph for this function:

◆ RefreshIV()

char * XrdCryptosslCipher::RefreshIV ( int &  l)
virtual

Reimplemented from XrdCryptoCipher.

Definition at line 1239 of file XrdCryptosslCipher.cc.

1240 {
1241  // Regenerate IV and return it
1242 
1243  // Generate a new IV
1244  GenerateIV();
1245 
1246  // Set output
1247  l = lIV;
1248  return fIV;
1249 }

◆ SetIV()

void XrdCryptosslCipher::SetIV ( int  l,
const char *  iv 
)
virtual

Reimplemented from XrdCryptoCipher.

Definition at line 1219 of file XrdCryptosslCipher.cc.

1220 {
1221  // Set IV from l bytes at iv. If !iv, sets the IV length.
1222 
1223  if (fIV) {
1224  delete[] fIV;
1225  fIV = 0;
1226  lIV = 0;
1227  }
1228 
1229  if (l > 0) {
1230  if (iv) {
1231  fIV = new char[l];
1232  if (fIV) memcpy(fIV,iv,l);
1233  }
1234  lIV = l;
1235  }
1236 }

Referenced by XrdCryptosslCipher().

+ Here is the caller graph for this function:

The documentation for this class was generated from the following files: