Skip to content

Commit ceba60d

Browse files
committed
crapi: add OpenSSL EVP digest backend
Extend the crapi layer with a third cryptographic backend, selectable at build time with -DWITH_CRYPTO=openssl. This gives users and distribution maintainers an additional choice of crypto provider alongside the existing gcrypt and NSS backends. One concrete motivation is deployments that restrict cryptographic operations to a FIPS 140-3 validated library: on those systems OpenSSL may be the only permitted provider, making this backend necessary to run the filehash probes. The implementation uses the OpenSSL EVP high-level digest API, which provides a stable, uniform interface across OpenSSL 1.0.x, 1.1.x, and 3.x. A compile-time compatibility shim aliases EVP_MD_CTX_new() and EVP_MD_CTX_free() to their pre-1.1.0 equivalents (EVP_MD_CTX_create() and EVP_MD_CTX_destroy()) for builds against older OpenSSL releases. Because OpenSSL is already an unconditional build dependency of OpenSCAP (required by xmlsec), selecting this backend introduces no new external dependency. The supported digest algorithms are SHA-224, SHA-256, SHA-384, SHA-512, and optionally MD5 and SHA-1 (governed by the existing OPENSCAP_ENABLE_MD5 and OPENSCAP_ENABLE_SHA1 flags). RIPEMD-160, which is gcrypt-specific and not part of the OVAL specification, is intentionally not included: its status in OpenSSL 3.x is deprecated and requires loading the legacy provider explicitly.
1 parent 657a4ff commit ceba60d

File tree

5 files changed

+155
-9
lines changed

5 files changed

+155
-9
lines changed

CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,21 @@ check_library_exists(pthread pthread_setname_np "" HAVE_PTHREAD_SETNAME_NP)
176176
check_library_exists(pthread pthread_getname_np "" HAVE_PTHREAD_GETNAME_NP)
177177

178178
# WITH_CRYPTO
179-
set(WITH_CRYPTO "gcrypt" CACHE STRING "gcrypt|nss")
179+
set(WITH_CRYPTO "gcrypt" CACHE STRING "gcrypt|nss|openssl")
180+
set_property(CACHE WITH_CRYPTO PROPERTY STRINGS "gcrypt" "nss" "openssl")
180181
if(${WITH_CRYPTO} STREQUAL "nss")
181182
message("-- Using NSS")
182183
find_package(NSS)
184+
elseif(${WITH_CRYPTO} STREQUAL "openssl")
185+
message("-- Using OpenSSL for crypto backend")
186+
# OpenSSL is already a required dependency (see find_package(OpenSSL REQUIRED) above);
187+
# this flag tells the crapi layer to use it as the digest backend.
188+
set(OPENSCAP_CRYPTO_OPENSSL TRUE)
183189
else()
184190
message("-- Using GCrypt")
185191
find_package(GCrypt)
186192
endif()
187-
if(GCRYPT_FOUND OR NSS_FOUND)
193+
if(GCRYPT_FOUND OR NSS_FOUND OR OPENSCAP_CRYPTO_OPENSSL)
188194
set(CRYPTO_FOUND TRUE)
189195
endif()
190196

config.h.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
#define HAVE_NSS3
2525
#endif
2626

27+
#cmakedefine OPENSCAP_CRYPTO_OPENSSL
28+
#if defined(OPENSCAP_CRYPTO_OPENSSL)
29+
#define HAVE_OPENSSL_CRYPTO
30+
#endif
31+
2732
#define OSCAP_DEFAULT_SCHEMA_PATH "@OSCAP_DEFAULT_SCHEMA_PATH@"
2833
#define OSCAP_DEFAULT_XSLT_PATH "@OSCAP_DEFAULT_XSLT_PATH@"
2934
#define OSCAP_DEFAULT_CPE_PATH "@OSCAP_DEFAULT_CPE_PATH@"

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ if (ENABLE_PROBES)
5959
)
6060
endif()
6161
endif()
62-
if (HAVE_MMAN_H AND (GCRYPT_FOUND OR NSS_FOUND))
62+
if (HAVE_MMAN_H AND (GCRYPT_FOUND OR NSS_FOUND OR OPENSCAP_CRYPTO_OPENSSL))
6363
list(APPEND OBJECTS_TO_LINK_AGAINST
6464
$<TARGET_OBJECTS:crapi_object>
6565
)

src/OVAL/probes/crapi/crapi.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,17 @@ int crapi_init (void *unused)
4747

4848
return(0);
4949
}
50+
#elif defined(HAVE_OPENSSL_CRYPTO)
51+
#include <openssl/evp.h>
52+
#include <openssl/opensslv.h>
53+
int crapi_init (void *unused)
54+
{
55+
#if OPENSSL_VERSION_NUMBER < 0x10100000L
56+
/* OpenSSL < 1.1.0 requires explicit digest algorithm registration. */
57+
OpenSSL_add_all_digests();
58+
#endif
59+
return (0);
60+
}
5061
#else
5162
int crapi_init (void *unused)
5263
{

src/OVAL/probes/crapi/digest.c

Lines changed: 130 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,23 @@
4141
#include <sechash.h>
4242
#elif defined(HAVE_GCRYPT)
4343
#include <gcrypt.h>
44+
#elif defined(HAVE_OPENSSL_CRYPTO)
45+
#include <openssl/evp.h>
46+
#include <openssl/opensslv.h>
4447
#else
4548
#error "No crypto library available!"
4649
#endif
4750

51+
/*
52+
* Compatibility shim for OpenSSL < 1.1.0, which used EVP_MD_CTX_create() and
53+
* EVP_MD_CTX_destroy() instead of the EVP_MD_CTX_new() / EVP_MD_CTX_free()
54+
* names introduced in 1.1.0.
55+
*/
56+
#if defined(HAVE_OPENSSL_CRYPTO) && OPENSSL_VERSION_NUMBER < 0x10100000L
57+
# define EVP_MD_CTX_new() EVP_MD_CTX_create()
58+
# define EVP_MD_CTX_free(c) EVP_MD_CTX_destroy(c)
59+
#endif
60+
4861
#if defined(HAVE_NSS3)
4962
static int crapi_alg_t_to_lib_arg(crapi_alg_t alg)
5063
{
@@ -95,6 +108,30 @@ static int crapi_alg_t_to_lib_arg(crapi_alg_t alg)
95108
return -1;
96109
}
97110
}
111+
#elif defined(HAVE_OPENSSL_CRYPTO)
112+
static const EVP_MD *crapi_alg_t_to_evp_md(crapi_alg_t alg)
113+
{
114+
switch (alg) {
115+
#ifdef OPENSCAP_ENABLE_MD5
116+
case CRAPI_DIGEST_MD5:
117+
return EVP_md5(); /* NOSONAR - MD5 is used for OVAL file integrity probes, not for security-sensitive purposes */
118+
#endif
119+
#ifdef OPENSCAP_ENABLE_SHA1
120+
case CRAPI_DIGEST_SHA1:
121+
return EVP_sha1(); /* NOSONAR - SHA-1 is used for OVAL file integrity probes, not for security-sensitive purposes */
122+
#endif
123+
case CRAPI_DIGEST_SHA224:
124+
return EVP_sha224();
125+
case CRAPI_DIGEST_SHA256:
126+
return EVP_sha256();
127+
case CRAPI_DIGEST_SHA384:
128+
return EVP_sha384();
129+
case CRAPI_DIGEST_SHA512:
130+
return EVP_sha512();
131+
default:
132+
return NULL;
133+
}
134+
}
98135
#endif
99136

100137
int crapi_digest_fd(int fd, crapi_alg_t alg, void *dst, size_t *size)
@@ -107,6 +144,22 @@ int crapi_digest_fd(int fd, crapi_alg_t alg, void *dst, size_t *size)
107144
errno = EFAULT;
108145
return -1;
109146
}
147+
148+
/*
149+
* Resolve the algorithm and verify the output buffer is large enough
150+
* to hold the digest.
151+
*/
152+
#if defined(HAVE_OPENSSL_CRYPTO)
153+
const EVP_MD *evp_md = crapi_alg_t_to_evp_md(alg);
154+
if (evp_md == NULL) {
155+
errno = EINVAL;
156+
return -1;
157+
}
158+
if (*size < (size_t)EVP_MD_size(evp_md)) {
159+
errno = ENOBUFS;
160+
return -1;
161+
}
162+
#else
110163
int lib_alg = crapi_alg_t_to_lib_arg(alg);
111164
#if defined(HAVE_NSS3)
112165
if (*size < HASH_ResultLen(lib_alg)) {
@@ -116,6 +169,7 @@ int crapi_digest_fd(int fd, crapi_alg_t alg, void *dst, size_t *size)
116169
errno = ENOBUFS;
117170
return -1;
118171
}
172+
#endif /* HAVE_OPENSSL_CRYPTO */
119173

120174
if (fstat (fd, &st) != 0)
121175
return (-1);
@@ -133,7 +187,15 @@ int crapi_digest_fd(int fd, crapi_alg_t alg, void *dst, size_t *size)
133187
ssize_t ret;
134188

135189
buffer = _buffer;
136-
#if defined(HAVE_NSS3)
190+
#if defined(HAVE_OPENSSL_CRYPTO)
191+
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
192+
if (ctx == NULL)
193+
return -1;
194+
if (EVP_DigestInit_ex(ctx, evp_md, NULL) != 1) {
195+
EVP_MD_CTX_free(ctx);
196+
return -1;
197+
}
198+
#elif defined(HAVE_NSS3)
137199
HASHContext *ctx = HASH_Create (lib_alg);
138200

139201
if (ctx == NULL)
@@ -144,7 +206,9 @@ int crapi_digest_fd(int fd, crapi_alg_t alg, void *dst, size_t *size)
144206
#endif
145207

146208
while ((ret = read(fd, buffer, sizeof _buffer)) == sizeof _buffer)
147-
#if defined(HAVE_NSS3)
209+
#if defined(HAVE_OPENSSL_CRYPTO)
210+
EVP_DigestUpdate(ctx, (const void *)buffer, sizeof _buffer);
211+
#elif defined(HAVE_NSS3)
148212
HASH_Update(ctx, (const unsigned char *)buffer, (unsigned int) sizeof _buffer);
149213
#elif defined(HAVE_GCRYPT)
150214
gcry_md_write(hd, (const void *)buffer, sizeof _buffer);
@@ -154,24 +218,39 @@ int crapi_digest_fd(int fd, crapi_alg_t alg, void *dst, size_t *size)
154218
case 0:
155219
break;
156220
case -1:
221+
#if defined(HAVE_OPENSSL_CRYPTO)
222+
EVP_MD_CTX_free(ctx);
223+
#endif
157224
return (-1);
158225
default:
159226
if (ret <= 0) {
160-
#if defined(HAVE_NSS3)
227+
#if defined(HAVE_OPENSSL_CRYPTO)
228+
EVP_MD_CTX_free(ctx);
229+
#elif defined(HAVE_NSS3)
161230
HASH_Destroy(ctx);
162231
#elif defined(HAVE_GCRYPT)
163232
gcry_md_close(hd);
164233
#endif
165234
return -1;
166235
}
167-
#if defined(HAVE_NSS3)
236+
#if defined(HAVE_OPENSSL_CRYPTO)
237+
EVP_DigestUpdate(ctx, (const void *)buffer, (size_t)ret);
238+
#elif defined(HAVE_NSS3)
168239
HASH_Update(ctx, (const unsigned char *)buffer, (unsigned int) ret);
169240
#elif defined(HAVE_GCRYPT)
170241
gcry_md_write(hd, (const void *)buffer, (size_t)ret);
171242
#endif
172243
}
173244

174-
#if defined(HAVE_NSS3)
245+
#if defined(HAVE_OPENSSL_CRYPTO)
246+
unsigned int md_len = (unsigned int)*size;
247+
if (EVP_DigestFinal_ex(ctx, (unsigned char *)dst, &md_len) != 1) {
248+
EVP_MD_CTX_free(ctx);
249+
return -1;
250+
}
251+
*size = (size_t)md_len;
252+
EVP_MD_CTX_free(ctx);
253+
#elif defined(HAVE_NSS3)
175254
HASH_End(ctx, dst, (unsigned int *)size, *size);
176255
HASH_Destroy(ctx);
177256
#elif defined(HAVE_GCRYPT)
@@ -184,7 +263,14 @@ int crapi_digest_fd(int fd, crapi_alg_t alg, void *dst, size_t *size)
184263

185264
#if _FILE_OFFSET_BITS == 32
186265
} else {
187-
#if defined(HAVE_NSS3)
266+
#if defined(HAVE_OPENSSL_CRYPTO)
267+
unsigned int md_len = (unsigned int)*size;
268+
if (EVP_Digest(buffer, buflen, (unsigned char *)dst, &md_len, evp_md, NULL) != 1) {
269+
munmap(buffer, buflen);
270+
return -1;
271+
}
272+
*size = (size_t)md_len;
273+
#elif defined(HAVE_NSS3)
188274
HASH_HashBuf(lib_alg, (unsigned char *)dst, (unsigned char *)buffer, (unsigned int)buflen);
189275
#elif defined(HAVE_GCRYPT)
190276
gcry_md_hash_buffer(lib_alg, dst, (const void *)buffer, buflen);
@@ -201,6 +287,8 @@ struct crapi_digest_ctx {
201287
HASHContext *ctx;
202288
#elif defined(HAVE_GCRYPT)
203289
gcry_md_hd_t ctx;
290+
#elif defined(HAVE_OPENSSL_CRYPTO)
291+
EVP_MD_CTX *ctx;
204292
#endif
205293
void *dst;
206294
size_t *size;
@@ -215,14 +303,35 @@ static void *crapi_digest_init (void *dst, void *size, crapi_alg_t alg)
215303
{
216304
struct crapi_digest_ctx *ctx = malloc(sizeof(struct crapi_digest_ctx));
217305

306+
#if defined(HAVE_NSS3) || defined(HAVE_GCRYPT)
218307
int lib_alg = crapi_alg_t_to_lib_arg(alg);
308+
#endif
219309
#if defined(HAVE_NSS3)
220310
ctx->ctx = HASH_Create(lib_alg);
221311
#elif defined(HAVE_GCRYPT)
222312
if (gcry_md_open(&ctx->ctx, lib_alg, 0) != 0) {
223313
free(ctx);
224314
return NULL;
225315
}
316+
#elif defined(HAVE_OPENSSL_CRYPTO)
317+
if (ctx == NULL)
318+
return NULL;
319+
const EVP_MD *evp_md = crapi_alg_t_to_evp_md(alg);
320+
if (evp_md == NULL) {
321+
free(ctx);
322+
errno = EINVAL;
323+
return NULL;
324+
}
325+
ctx->ctx = EVP_MD_CTX_new();
326+
if (ctx->ctx == NULL) {
327+
free(ctx);
328+
return NULL;
329+
}
330+
if (EVP_DigestInit_ex(ctx->ctx, evp_md, NULL) != 1) {
331+
EVP_MD_CTX_free(ctx->ctx);
332+
free(ctx);
333+
return NULL;
334+
}
226335
#endif
227336
ctx->dst = dst;
228337
ctx->size = size;
@@ -245,6 +354,9 @@ static int crapi_digest_update(struct crapi_digest_ctx *ctx, void *bptr, size_t
245354
HASH_Update(ctx->ctx, (const unsigned char *)bptr, (unsigned int)blen);
246355
#elif defined(HAVE_GCRYPT)
247356
gcry_md_write(ctx->ctx, (const void *)bptr, blen);
357+
#elif defined(HAVE_OPENSSL_CRYPTO)
358+
if (EVP_DigestUpdate(ctx->ctx, (const void *)bptr, blen) != 1)
359+
return -1;
248360
#endif
249361
return (0);
250362
}
@@ -264,6 +376,15 @@ static int crapi_digest_fini(struct crapi_digest_ctx *ctx, crapi_alg_t alg)
264376
buffer = (void *)gcry_md_read(ctx->ctx, lib_alg);
265377
memcpy(ctx->dst, buffer, gcry_md_get_algo_dlen(lib_alg));
266378
gcry_md_close(ctx->ctx);
379+
#elif defined(HAVE_OPENSSL_CRYPTO)
380+
unsigned int md_len = (unsigned int)*ctx->size;
381+
if (EVP_DigestFinal_ex(ctx->ctx, (unsigned char *)ctx->dst, &md_len) != 1) {
382+
EVP_MD_CTX_free(ctx->ctx);
383+
free(ctx);
384+
return -1;
385+
}
386+
*ctx->size = (size_t)md_len;
387+
EVP_MD_CTX_free(ctx->ctx);
267388
#endif
268389
free (ctx);
269390

@@ -275,6 +396,9 @@ static void crapi_digest_free(struct crapi_digest_ctx *ctx)
275396
#if defined(HAVE_NSS3)
276397
HASH_Destroy(ctx->ctx);
277398
free(ctx);
399+
#elif defined(HAVE_OPENSSL_CRYPTO)
400+
EVP_MD_CTX_free(ctx->ctx);
401+
free(ctx);
278402
#endif
279403
return;
280404
}

0 commit comments

Comments
 (0)