Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,20 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
*/
private static final FileFilter OPENSSLV_FILTER = FileFilterBuilder.newInstance().addFilenames(OPENSSLV_H).build();
/**
* Open SSL Version number pattern.
* Open SSL Version number pattern (OpenSSL 1.x and earlier — literal hex constant).
*/
private static final Pattern VERSION_PATTERN = Pattern.compile(
"define\\s+OPENSSL_VERSION_NUMBER\\s+0x([0-9a-zA-Z]{8})L", Pattern.DOTALL
| Pattern.CASE_INSENSITIVE);
/**
* Open SSL version string pattern (OpenSSL 3.x — {@code OPENSSL_VERSION_STR "X.Y.Z"}).
* In 3.x, {@code OPENSSL_VERSION_NUMBER} is a macro expression that the
* legacy {@link #VERSION_PATTERN} cannot match, so this is the authoritative
* source of the version on 3.x headers.
*/
private static final Pattern VERSION_STR_PATTERN = Pattern.compile(
"define\\s+OPENSSL_VERSION_STR\\s+\"([^\"]+)\"", Pattern.DOTALL
| Pattern.CASE_INSENSITIVE);
/**
* The offset of the major version number.
*/
Expand Down Expand Up @@ -191,28 +200,31 @@ protected void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
final File file = dependency.getActualFile();
final String parentName = file.getParentFile().getName();
boolean found = false;
final String contents = getFileContents(file);
String version = null;
if (!contents.isEmpty()) {
final Matcher matcher = VERSION_PATTERN.matcher(contents);
if (matcher.find()) {
found = true;
final String version = getOpenSSLVersion(Long.parseLong(matcher.group(1), HEXADECIMAL));
dependency.addEvidence(EvidenceType.VERSION, OPENSSLV_H, "Version Constant",
version, Confidence.HIGH);
try {
final PackageURL purl = PackageURLBuilder.aPackageURL().withType("generic")
.withName("openssl").withVersion(version).build();
dependency.addSoftwareIdentifier(new PurlIdentifier(purl, Confidence.HIGHEST));
} catch (MalformedPackageURLException ex) {
LOGGER.debug("Unable to build package url for openssl", ex);
final GenericIdentifier id = new GenericIdentifier("generic:openssl@" + version, Confidence.HIGHEST);
dependency.addSoftwareIdentifier(id);
final Matcher strMatcher = VERSION_STR_PATTERN.matcher(contents);
if (strMatcher.find()) {
version = strMatcher.group(1);
} else {
final Matcher matcher = VERSION_PATTERN.matcher(contents);
if (matcher.find()) {
version = getOpenSSLVersion(Long.parseLong(matcher.group(1), HEXADECIMAL));
}

}
}
if (found) {
if (version != null) {
dependency.addEvidence(EvidenceType.VERSION, OPENSSLV_H, "Version Constant",
version, Confidence.HIGH);
try {
final PackageURL purl = PackageURLBuilder.aPackageURL().withType("generic")
.withName("openssl").withVersion(version).build();
dependency.addSoftwareIdentifier(new PurlIdentifier(purl, Confidence.HIGHEST));
} catch (MalformedPackageURLException ex) {
LOGGER.debug("Unable to build package url for openssl", ex);
final GenericIdentifier id = new GenericIdentifier("generic:openssl@" + version, Confidence.HIGHEST);
dependency.addSoftwareIdentifier(id);
}
dependency.setDisplayFileName(parentName + File.separatorChar + OPENSSLV_H);
dependency.addEvidence(EvidenceType.VENDOR, OPENSSLV_H, "Vendor", "OpenSSL", Confidence.HIGHEST);
dependency.addEvidence(EvidenceType.PRODUCT, OPENSSLV_H, "Product", "OpenSSL", Confidence.HIGHEST);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,15 @@ void testOpenSSLVersionHeaderFile() throws AnalysisException {
assertThat(result.getEvidence(EvidenceType.VENDOR).toString(), containsString("OpenSSL"));
assertThat(result.getEvidence(EvidenceType.VERSION).toString(), containsString("1.0.2c"));
}

@Test
void testOpenSSL3xVersionHeaderFile() throws AnalysisException {
final Dependency result = new Dependency(BaseTest.getResourceAsFile(
this,
"openssl-3x/opensslv.h"));
analyzer.analyze(result, null);
assertThat(result.getEvidence(EvidenceType.PRODUCT).toString(), containsString("OpenSSL"));
assertThat(result.getEvidence(EvidenceType.VENDOR).toString(), containsString("OpenSSL"));
assertThat(result.getEvidence(EvidenceType.VERSION).toString(), containsString("3.5.6"));
}
}
131 changes: 131 additions & 0 deletions core/src/test/resources/openssl-3x/opensslv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* WARNING: do not edit!
* Generated by Makefile from include/openssl/opensslv.h.in
*
* Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/

#ifndef OPENSSL_OPENSSLV_H
#define OPENSSL_OPENSSLV_H
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

/*
* SECTION 1: VERSION DATA. These will change for each release
*/

/*
* Base version macros
*
* These macros express version number MAJOR.MINOR.PATCH exactly
*/
/* clang-format off */
# define OPENSSL_VERSION_MAJOR 3
/* clang-format on */
/* clang-format off */
# define OPENSSL_VERSION_MINOR 5
/* clang-format on */
/* clang-format off */
# define OPENSSL_VERSION_PATCH 6
/* clang-format on */

/*
* Additional version information
*
* These are also part of the new version scheme, but aren't part
* of the version number itself.
*/

/* Could be: #define OPENSSL_VERSION_PRE_RELEASE "-alpha.1" */
/* clang-format off */
# define OPENSSL_VERSION_PRE_RELEASE ""
/* clang-format on */
/* Could be: #define OPENSSL_VERSION_BUILD_METADATA "+fips" */
/* Could be: #define OPENSSL_VERSION_BUILD_METADATA "+vendor.1" */
/* clang-format off */
# define OPENSSL_VERSION_BUILD_METADATA ""
/* clang-format on */

/*
* Note: The OpenSSL Project will never define OPENSSL_VERSION_BUILD_METADATA
* to be anything but the empty string. Its use is entirely reserved for
* others
*/

/*
* Shared library version
*
* This is strictly to express ABI version, which may or may not
* be related to the API version expressed with the macros above.
* This is defined in free form.
*/
/* clang-format off */
# define OPENSSL_SHLIB_VERSION 3
/* clang-format on */

/*
* SECTION 2: USEFUL MACROS
*/

/* For checking general API compatibility when preprocessing */
#define OPENSSL_VERSION_PREREQ(maj, min) \
((OPENSSL_VERSION_MAJOR << 16) + OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min))

/*
* Macros to get the version in easily digested string form, both the short
* "MAJOR.MINOR.PATCH" variant (where MAJOR, MINOR and PATCH are replaced
* with the values from the corresponding OPENSSL_VERSION_ macros) and the
* longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
* OPENSSL_VERSION_BUILD_METADATA_STR appended.
*/
/* clang-format off */
# define OPENSSL_VERSION_STR "3.5.6"
/* clang-format on */
/* clang-format off */
# define OPENSSL_FULL_VERSION_STR "3.5.6"
/* clang-format on */

/*
* SECTION 3: ADDITIONAL METADATA
*
* These strings are defined separately to allow them to be parsable.
*/
/* clang-format off */
# define OPENSSL_RELEASE_DATE "7 Apr 2026"
/* clang-format on */

/*
* SECTION 4: BACKWARD COMPATIBILITY
*/

/* clang-format off */
# define OPENSSL_VERSION_TEXT "OpenSSL 3.5.6 7 Apr 2026"
/* clang-format on */

/* clang-format off */
/* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PP0L */
# define OPENSSL_VERSION_NUMBER \
( (OPENSSL_VERSION_MAJOR<<28) \
|(OPENSSL_VERSION_MINOR<<20) \
|(OPENSSL_VERSION_PATCH<<4) \
|0x0L )
/* clang-format on */

#ifdef __cplusplus
}
#endif

#include <openssl/macros.h>
#ifndef OPENSSL_NO_DEPRECATED_3_0
#define HEADER_OPENSSLV_H
#endif

#endif /* OPENSSL_OPENSSLV_H */
Loading