XRootD
Loading...
Searching...
No Matches
XrdCryptoLite_BFecb.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d C r y p t o L i t e _ B F e c b . c c */
4/* */
5/* (c) 2026 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Department of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#include <openssl/evp.h>
31#if OPENSSL_VERSION_NUMBER >= 0x30000000L
32#include <openssl/provider.h>
33#endif
34
36#include "XrdOuc/XrdOucUtils.hh"
37
38/******************************************************************************/
39/* C o n s t r u c t o r */
40/******************************************************************************/
41
43 const unsigned char* key,
44 unsigned int keylen)
45 : decCTX(0), encCTX(0)
46{
47#if OPENSSL_VERSION_NUMBER >= 0x30000000L
48// With openssl v3 the blowfish cipher is only available via the "legacy"
49// provider. Legacy is typically not enabled by default (but can be via
50// openssl.cnf) so it is loaded here. Explicitly loading a provider will
51// disable the automatic loading of the "default" one. The default might
52// not have already been loaded, or standard algorithms might be available
53// via another configured provider, such as FIPS. So an attempt is made to
54// fetch a common default algorithm, possibly automaticlly loading the
55// default provider. Afterwards the legacy provider is loaded.
56//
57 static struct loadProviders {
58 loadProviders() {
59 EVP_MD *mdp = EVP_MD_fetch(NULL, "SHA2-256", NULL);
60 if (mdp) EVP_MD_free(mdp);
61 // Load legacy provider into the default (NULL) library context
62 (void) OSSL_PROVIDER_load(NULL, "legacy");
63 }
64 } lp;
65#endif
66
67// Handle auto generation of a random key
68//
69 unsigned char bfKey[16];
70 if (!key || !keylen)
71 {XrdOucUtils::Random(bfKey, sizeof(bfKey));
72 key = bfKey;
73 keylen = sizeof(bfKey);
74 }
75
76// The legacy openssl EVP is rather outdated, cumbersome, non thread-safe,
77// and badly documented. Unfortunately, it is the only one generally availabe
78// on all platforms (modern versions like CryptoPP need manual installation).
79// So, we need to construct a decryption context and an encryption context
80// because the context can only do one type of action at a time and resetting
81// the key when switching actions is CPU intensive. What a pain in the but!
82//
83 aOK = false;
84 if (!(decCTX = EVP_CIPHER_CTX_new())) return;
85 if (1 != EVP_DecryptInit_ex(decCTX, EVP_bf_ecb(), NULL, NULL, NULL)) return;
86 EVP_CIPHER_CTX_set_padding(decCTX, 0);
87 EVP_CIPHER_CTX_set_key_length(decCTX, keylen);
88 if (1 != EVP_DecryptInit_ex(decCTX, NULL, NULL, key, NULL)) return;
89
90 if (!(encCTX = EVP_CIPHER_CTX_new())) return;
91 if (1 != EVP_EncryptInit_ex(encCTX, EVP_bf_ecb(), NULL, NULL, NULL)) return;
92 EVP_CIPHER_CTX_set_padding(encCTX, 0);
93 EVP_CIPHER_CTX_set_key_length(encCTX, keylen);
94 if (1 != EVP_EncryptInit_ex(encCTX, NULL, NULL, key, NULL)) return;
95 aOK = true;
96}
97
98/******************************************************************************/
99/* D e s t r u c t o r */
100/******************************************************************************/
101
103{
104 EVP_CIPHER_CTX_free(decCTX);
105 EVP_CIPHER_CTX_free(encCTX);
106}
107
108/******************************************************************************/
109/* D e c r y p t */
110/******************************************************************************/
111
112void XrdCryptoLite_BFecb::Decrypt(const unsigned char* in8,
113 unsigned char* out8)
114{
115 int dlen;
116
117// Perform the action. Since we said padding is zero and the input must be
118// 8 bytes, and we are using blowfish ECB when we decrypt the result will
119// not be buffered but placed in the output buffer upon return.
120//
121 evpMutex.Lock();
122 EVP_DecryptUpdate(decCTX, out8, &dlen, in8, 8);
123 evpMutex.UnLock();
124}
125
126/******************************************************************************/
127/* E n c r y p t */
128/******************************************************************************/
129
130void XrdCryptoLite_BFecb::Encrypt(const unsigned char* in8,
131 unsigned char* out8)
132{
133 int dlen;
134
135// Perform the action
136//
137// Perform the action. Since we said padding is zero and the input must be
138// 8 bytes, and we are using blowfish ECB when we encrypt the result will
139// not be buffered but placed in the output buffer upon return.
140//
141 evpMutex.Lock();
142 EVP_EncryptUpdate(encCTX, out8, &dlen, in8, 8);
143 evpMutex.UnLock();
144}
145
146/******************************************************************************/
147/* Static: I n s t a n c e */
148/******************************************************************************/
149
151 unsigned int klen)
152{
154 bool isOK;
155
156// Get an instance or return a nil pointer
157//
158 obj = new XrdCryptoLite_BFecb(isOK, key, klen);
159 if (!isOK) {delete obj; obj = 0;}
160 return obj;
161}
static XrdCryptoLite_BFecb * Instance(const unsigned char *key=0, unsigned int klen=0)
XrdCryptoLite_BFecb(bool &aOK, const unsigned char *key=0, unsigned int keylen=0)
void Decrypt(const unsigned char *in8, unsigned char *out8)
void Encrypt(const unsigned char *in8, unsigned char *out8)
static void Random(unsigned char *buff, unsigned int inblen)