XRootD
Loading...
Searching...
No Matches
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 ()
 
virtual XrdSutBucketAsBucket ()
 
virtual int DecOutLength (int l)
 
virtual int Decrypt (const char *in, int lin, char *out)
 
int Decrypt (XrdSutBucket &buck, bool useiv=true)
 
virtual int EncOutLength (int l)
 
virtual int Encrypt (const char *in, int lin, char *out)
 
int Encrypt (XrdSutBucket &buck, bool useiv=true)
 
virtual bool Finalize (bool padded, char *pub, int lpub, const char *t)
 
bool Finalize (char *pub, int lpub, const char *t)
 
virtual bool IsDefaultLength () const
 
virtual bool IsValid ()
 
virtual char * IV (int &l) const
 
virtual int MaxIVLength () const
 
virtual char * Public (int &lpub)
 
virtual char * RefreshIV (int &l)
 
virtual void SetIV (int l, const char *iv)
 
- Public Member Functions inherited from XrdCryptoBasic
 XrdCryptoBasic (const char *t=0, int l=0, const char *b=0)
 
virtual ~XrdCryptoBasic ()
 
virtual XrdSutBucketAsBucket ()
 
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)

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)
#define EPNAME(x)
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.

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(), 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(), XrdCryptosslCipher(), and XrdCryptosslCipher().

+ Here is the caller graph for this function:

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