Merged
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 numberDiff line numberDiff line change
Expand Up@@ -17,7 +17,7 @@ extends:

containers:
linux_arm:
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0-20240507035943-1390eea
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0
env:
ROOTFS_DIR: /crossrootfs/arm

Expand Down
4 changes: 2 additions & 2 deletions eng/pipelines/coreclr/templates/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -63,9 +63,9 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if eq(variables['System.TeamProject'], 'public') }}:
- (Ubuntu.1804.Arm32.Open)Ubuntu.2004.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- (Ubuntu.1804.Arm32)Ubuntu.2004.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32)Ubuntu.2004.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux arm64
- ${{ if eq(parameters.platform, 'linux_arm64') }}:
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/libraries/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if or(eq(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (Debian.11.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux armv6
- ${{ if eq(parameters.platform, 'linux_armv6') }}:
Expand Down
14 changes: 14 additions & 0 deletions src/native/libs/System.Security.Cryptography.Native/openssl.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -964,6 +964,20 @@ int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx,
return 0;
}

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
if (g_libSslUses32BitTime)
{
if (verifyTime > INT_MAX || verifyTime < INT_MIN)
{
return 0;
}

// Cast to a signature that takes a 32-bit value for the time.
((void (*)(X509_VERIFY_PARAM*, int32_t))(void*)(X509_VERIFY_PARAM_set_time))(verifyParams, (int32_t)verifyTime);
return 1;
}
#endif

X509_VERIFY_PARAM_set_time(verifyParams, verifyTime);
return 1;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,6 +25,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
TYPEOF(OPENSSL_gmtime) OPENSSL_gmtime_ptr;
#endif

// x.x.x, considering the max number of decimal digits for each component
#define MaxVersionStringLength 32
Expand All@@ -41,6 +44,15 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define MAKELIB(v) SONAME_BASE v
#endif

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
Comment thread
sbomer marked this conversation as resolved.
// We support ARM32 linux distros that have Y2038-compatible glibc (those which support _TIME_BITS).
// Some such distros have not yet switched to _TIME_BITS=64 by default, so we may be running against an openssl
// that expects 32-bit time_t even though our time_t is 64-bit.
// This can be deleted once the minimum supported Linux Arm32 distros are
// at least Debian 13 and Ubuntu 24.04.
bool g_libSslUses32BitTime = false;
#endif

static void DlOpen(const char* libraryName)
{
void* libsslNew = dlopen(libraryName, RTLD_LAZY);
Expand DownExpand Up@@ -205,6 +217,10 @@ void InitializeOpenSSLShim(void)
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
if (!(OPENSSL_gmtime_ptr = (TYPEOF(OPENSSL_gmtime))(dlsym(libssl, "OPENSSL_gmtime")))) { fprintf(stderr, "Cannot get required symbol OPENSSL_gmtime from libssl\n"); abort(); }
#endif


// Sanity check that we have at least one functioning way of reporting errors.
if (ERR_put_error_ptr == &local_ERR_put_error)
Expand All@@ -215,4 +231,23 @@ void InitializeOpenSSLShim(void)
abort();
}
}

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
// This value will represent a time in year 2038 if 64-bit time is used,
// or 1901 if the lower 32 bits are interpreted as a 32-bit time_t value.
time_t timeVal = (time_t)INT_MAX + 1;
struct tm tmVal = { 0 };

// Detect whether openssl is using 32-bit or 64-bit time_t.
// If it uses 32-bit time_t, little-endianness means that the pointer
// will be interpreted as a pointer to the lower 32 bits of timeVal.
// tm_year is the number of years since 1900.
if (!OPENSSL_gmtime(&timeVal, &tmVal) || (tmVal.tm_year != 138 && tmVal.tm_year != 1))
{
fprintf(stderr, "Cannot determine the time_t size used by libssl\n");
abort();
}

g_libSslUses32BitTime = (tmVal.tm_year == 1);
#endif
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,6 +187,10 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);

#define API_EXISTS(fn) (fn != NULL)

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
extern bool g_libSslUses32BitTime;
#endif

// List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
// Forgetting to add a function here results in build failure with message reporting the function
// that needs to be added.
Expand DownExpand Up@@ -618,7 +622,6 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);
REQUIRED_FUNCTION(SSL_version) \
FALLBACK_FUNCTION(X509_check_host) \
REQUIRED_FUNCTION(X509_check_purpose) \
REQUIRED_FUNCTION(X509_cmp_current_time) \
REQUIRED_FUNCTION(X509_cmp_time) \
REQUIRED_FUNCTION(X509_CRL_free) \
FALLBACK_FUNCTION(X509_CRL_get0_nextUpdate) \
Expand DownExpand Up@@ -717,7 +720,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr;
#endif
// Redefine all calls to OpenSSL functions as calls through pointers that are set
// to the functions from the libssl.so selected by the shim.
#define a2d_ASN1_OBJECT a2d_ASN1_OBJECT_ptr
Expand DownExpand Up@@ -1018,6 +1023,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define OCSP_RESPONSE_new OCSP_RESPONSE_new_ptr
#define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algorithms_conf_ptr
#define OPENSSL_cleanse OPENSSL_cleanse_ptr
#define OPENSSL_gmtime OPENSSL_gmtime_ptr
#define OPENSSL_init_ssl OPENSSL_init_ssl_ptr
#define OPENSSL_sk_free OPENSSL_sk_free_ptr
#define OPENSSL_sk_new_null OPENSSL_sk_new_null_ptr
Expand DownExpand Up@@ -1149,7 +1155,6 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define TLS_method TLS_method_ptr
#define X509_check_host X509_check_host_ptr
#define X509_check_purpose X509_check_purpose_ptr
#define X509_cmp_current_time X509_cmp_current_time_ptr
#define X509_cmp_time X509_cmp_time_ptr
#define X509_CRL_free X509_CRL_free_ptr
#define X509_CRL_get0_nextUpdate X509_CRL_get0_nextUpdate_ptr
Expand Down
53 changes: 30 additions & 23 deletions src/native/libs/System.Security.Cryptography.Native/pal_x509.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -893,14 +893,12 @@ static OCSP_CERTID* MakeCertId(X509* subject, X509* issuer)
return OCSP_cert_to_id(EVP_sha1(), subject, issuer);
}

static time_t GetIssuanceWindowStart(void)
static time_t GetIssuanceWindowStart(time_t currentTime)
{
// time_t granularity is seconds, so subtract 4 days worth of seconds.
// The 4 day policy is based on the CA/Browser Forum Baseline Requirements
// (version 1.6.3) section 4.9.10 (On-Line Revocation Checking Requirements)
time_t t = time(NULL);
t -= 4 * 24 * 60 * 60;
return t;
return currentTime - 4 * 24 * 60 * 60;
}

static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
Expand DownExpand Up@@ -960,28 +958,37 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,

if (OCSP_resp_find_status(basicResp, certId, &status, NULL, NULL, &thisupd, &nextupd))
{
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
int nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_current_time(nextupd);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else
time_t currentTime = time(NULL);
int nextUpdComparison = 0;
#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
// If openssl uses 32-bit time_t and the current time doesn't fit in 32 bits,
// skip checking the status/nextupd, and fall through to return PAL_X509_V_ERR_UNABLE_TO_GET_CRL.
if (!g_libSslUses32BitTime || (currentTime >= INT_MIN && currentTime <= INT_MAX))
#endif
{
if (nextupd != NULL && nextUpdComparison <= 0)
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_time(nextupd, &currentTime);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
else
{
ret = PAL_X509_V_OK;
if (nextupd != NULL && nextUpdComparison <= 0)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
{
ret = PAL_X509_V_OK;
}
}
}

Expand All@@ -997,7 +1004,7 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
thisupd != NULL &&
nextUpdComparison > 0)
{
time_t oldest = GetIssuanceWindowStart();
time_t oldest = GetIssuanceWindowStart(currentTime);

if (X509_cmp_time(thisupd, &oldest) > 0)
{
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
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 numberDiff line numberDiff line change
Expand Up@@ -17,7 +17,7 @@ extends:

containers:
linux_arm:
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0-20240507035943-1390eea
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0
env:
ROOTFS_DIR: /crossrootfs/arm

Expand Down
4 changes: 2 additions & 2 deletions eng/pipelines/coreclr/templates/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -63,9 +63,9 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if eq(variables['System.TeamProject'], 'public') }}:
- (Ubuntu.1804.Arm32.Open)Ubuntu.2004.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- (Ubuntu.1804.Arm32)Ubuntu.2004.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32)Ubuntu.2004.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux arm64
- ${{ if eq(parameters.platform, 'linux_arm64') }}:
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/libraries/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if or(eq(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (Debian.11.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux armv6
- ${{ if eq(parameters.platform, 'linux_armv6') }}:
Expand Down
14 changes: 14 additions & 0 deletions src/native/libs/System.Security.Cryptography.Native/openssl.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -964,6 +964,20 @@ int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx,
return 0;
}

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
if (g_libSslUses32BitTime)
{
if (verifyTime > INT_MAX || verifyTime < INT_MIN)
{
return 0;
}

// Cast to a signature that takes a 32-bit value for the time.
((void (*)(X509_VERIFY_PARAM*, int32_t))(void*)(X509_VERIFY_PARAM_set_time))(verifyParams, (int32_t)verifyTime);
return 1;
}
#endif

X509_VERIFY_PARAM_set_time(verifyParams, verifyTime);
return 1;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,6 +25,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
TYPEOF(OPENSSL_gmtime) OPENSSL_gmtime_ptr;
#endif

// x.x.x, considering the max number of decimal digits for each component
#define MaxVersionStringLength 32
Expand All@@ -41,6 +44,15 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define MAKELIB(v) SONAME_BASE v
#endif

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
Comment thread
sbomer marked this conversation as resolved.
// We support ARM32 linux distros that have Y2038-compatible glibc (those which support _TIME_BITS).
// Some such distros have not yet switched to _TIME_BITS=64 by default, so we may be running against an openssl
// that expects 32-bit time_t even though our time_t is 64-bit.
// This can be deleted once the minimum supported Linux Arm32 distros are
// at least Debian 13 and Ubuntu 24.04.
bool g_libSslUses32BitTime = false;
#endif

static void DlOpen(const char* libraryName)
{
void* libsslNew = dlopen(libraryName, RTLD_LAZY);
Expand DownExpand Up@@ -205,6 +217,10 @@ void InitializeOpenSSLShim(void)
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
if (!(OPENSSL_gmtime_ptr = (TYPEOF(OPENSSL_gmtime))(dlsym(libssl, "OPENSSL_gmtime")))) { fprintf(stderr, "Cannot get required symbol OPENSSL_gmtime from libssl\n"); abort(); }
#endif


// Sanity check that we have at least one functioning way of reporting errors.
if (ERR_put_error_ptr == &local_ERR_put_error)
Expand All@@ -215,4 +231,23 @@ void InitializeOpenSSLShim(void)
abort();
}
}

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
// This value will represent a time in year 2038 if 64-bit time is used,
// or 1901 if the lower 32 bits are interpreted as a 32-bit time_t value.
time_t timeVal = (time_t)INT_MAX + 1;
struct tm tmVal = { 0 };

// Detect whether openssl is using 32-bit or 64-bit time_t.
// If it uses 32-bit time_t, little-endianness means that the pointer
// will be interpreted as a pointer to the lower 32 bits of timeVal.
// tm_year is the number of years since 1900.
if (!OPENSSL_gmtime(&timeVal, &tmVal) || (tmVal.tm_year != 138 && tmVal.tm_year != 1))
{
fprintf(stderr, "Cannot determine the time_t size used by libssl\n");
abort();
}

g_libSslUses32BitTime = (tmVal.tm_year == 1);
#endif
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,6 +187,10 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);

#define API_EXISTS(fn) (fn != NULL)

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
extern bool g_libSslUses32BitTime;
#endif

// List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
// Forgetting to add a function here results in build failure with message reporting the function
// that needs to be added.
Expand DownExpand Up@@ -618,7 +622,6 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);
REQUIRED_FUNCTION(SSL_version) \
FALLBACK_FUNCTION(X509_check_host) \
REQUIRED_FUNCTION(X509_check_purpose) \
REQUIRED_FUNCTION(X509_cmp_current_time) \
REQUIRED_FUNCTION(X509_cmp_time) \
REQUIRED_FUNCTION(X509_CRL_free) \
FALLBACK_FUNCTION(X509_CRL_get0_nextUpdate) \
Expand DownExpand Up@@ -717,7 +720,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr;
#endif
// Redefine all calls to OpenSSL functions as calls through pointers that are set
// to the functions from the libssl.so selected by the shim.
#define a2d_ASN1_OBJECT a2d_ASN1_OBJECT_ptr
Expand DownExpand Up@@ -1018,6 +1023,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define OCSP_RESPONSE_new OCSP_RESPONSE_new_ptr
#define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algorithms_conf_ptr
#define OPENSSL_cleanse OPENSSL_cleanse_ptr
#define OPENSSL_gmtime OPENSSL_gmtime_ptr
#define OPENSSL_init_ssl OPENSSL_init_ssl_ptr
#define OPENSSL_sk_free OPENSSL_sk_free_ptr
#define OPENSSL_sk_new_null OPENSSL_sk_new_null_ptr
Expand DownExpand Up@@ -1149,7 +1155,6 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define TLS_method TLS_method_ptr
#define X509_check_host X509_check_host_ptr
#define X509_check_purpose X509_check_purpose_ptr
#define X509_cmp_current_time X509_cmp_current_time_ptr
#define X509_cmp_time X509_cmp_time_ptr
#define X509_CRL_free X509_CRL_free_ptr
#define X509_CRL_get0_nextUpdate X509_CRL_get0_nextUpdate_ptr
Expand Down
53 changes: 30 additions & 23 deletions src/native/libs/System.Security.Cryptography.Native/pal_x509.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -893,14 +893,12 @@ static OCSP_CERTID* MakeCertId(X509* subject, X509* issuer)
return OCSP_cert_to_id(EVP_sha1(), subject, issuer);
}

static time_t GetIssuanceWindowStart(void)
static time_t GetIssuanceWindowStart(time_t currentTime)
{
// time_t granularity is seconds, so subtract 4 days worth of seconds.
// The 4 day policy is based on the CA/Browser Forum Baseline Requirements
// (version 1.6.3) section 4.9.10 (On-Line Revocation Checking Requirements)
time_t t = time(NULL);
t -= 4 * 24 * 60 * 60;
return t;
return currentTime - 4 * 24 * 60 * 60;
}

static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
Expand DownExpand Up@@ -960,28 +958,37 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,

if (OCSP_resp_find_status(basicResp, certId, &status, NULL, NULL, &thisupd, &nextupd))
{
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
int nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_current_time(nextupd);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else
time_t currentTime = time(NULL);
int nextUpdComparison = 0;
#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
// If openssl uses 32-bit time_t and the current time doesn't fit in 32 bits,
// skip checking the status/nextupd, and fall through to return PAL_X509_V_ERR_UNABLE_TO_GET_CRL.
if (!g_libSslUses32BitTime || (currentTime >= INT_MIN && currentTime <= INT_MAX))
#endif
{
if (nextupd != NULL && nextUpdComparison <= 0)
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_time(nextupd, &currentTime);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
else
{
ret = PAL_X509_V_OK;
if (nextupd != NULL && nextUpdComparison <= 0)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
{
ret = PAL_X509_V_OK;
}
}
}

Expand All@@ -997,7 +1004,7 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
thisupd != NULL &&
nextUpdComparison > 0)
{
time_t oldest = GetIssuanceWindowStart();
time_t oldest = GetIssuanceWindowStart(currentTime);

if (X509_cmp_time(thisupd, &oldest) > 0)
{
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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 numberDiff line numberDiff line change
Expand Up@@ -17,7 +17,7 @@ extends:

containers:
linux_arm:
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0-20240507035943-1390eea
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0
env:
ROOTFS_DIR: /crossrootfs/arm

Expand Down
4 changes: 2 additions & 2 deletions eng/pipelines/coreclr/templates/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -63,9 +63,9 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if eq(variables['System.TeamProject'], 'public') }}:
- (Ubuntu.1804.Arm32.Open)Ubuntu.2004.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- (Ubuntu.1804.Arm32)Ubuntu.2004.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32)Ubuntu.2004.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux arm64
- ${{ if eq(parameters.platform, 'linux_arm64') }}:
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/libraries/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if or(eq(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (Debian.11.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux armv6
- ${{ if eq(parameters.platform, 'linux_armv6') }}:
Expand Down
14 changes: 14 additions & 0 deletions src/native/libs/System.Security.Cryptography.Native/openssl.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -964,6 +964,20 @@ int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx,
return 0;
}

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
if (g_libSslUses32BitTime)
{
if (verifyTime > INT_MAX || verifyTime < INT_MIN)
{
return 0;
}

// Cast to a signature that takes a 32-bit value for the time.
((void (*)(X509_VERIFY_PARAM*, int32_t))(void*)(X509_VERIFY_PARAM_set_time))(verifyParams, (int32_t)verifyTime);
return 1;
}
#endif

X509_VERIFY_PARAM_set_time(verifyParams, verifyTime);
return 1;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,6 +25,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
TYPEOF(OPENSSL_gmtime) OPENSSL_gmtime_ptr;
#endif

// x.x.x, considering the max number of decimal digits for each component
#define MaxVersionStringLength 32
Expand All@@ -41,6 +44,15 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define MAKELIB(v) SONAME_BASE v
#endif

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
Comment thread
sbomer marked this conversation as resolved.
// We support ARM32 linux distros that have Y2038-compatible glibc (those which support _TIME_BITS).
// Some such distros have not yet switched to _TIME_BITS=64 by default, so we may be running against an openssl
// that expects 32-bit time_t even though our time_t is 64-bit.
// This can be deleted once the minimum supported Linux Arm32 distros are
// at least Debian 13 and Ubuntu 24.04.
bool g_libSslUses32BitTime = false;
#endif

static void DlOpen(const char* libraryName)
{
void* libsslNew = dlopen(libraryName, RTLD_LAZY);
Expand DownExpand Up@@ -205,6 +217,10 @@ void InitializeOpenSSLShim(void)
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
if (!(OPENSSL_gmtime_ptr = (TYPEOF(OPENSSL_gmtime))(dlsym(libssl, "OPENSSL_gmtime")))) { fprintf(stderr, "Cannot get required symbol OPENSSL_gmtime from libssl\n"); abort(); }
#endif


// Sanity check that we have at least one functioning way of reporting errors.
if (ERR_put_error_ptr == &local_ERR_put_error)
Expand All@@ -215,4 +231,23 @@ void InitializeOpenSSLShim(void)
abort();
}
}

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
// This value will represent a time in year 2038 if 64-bit time is used,
// or 1901 if the lower 32 bits are interpreted as a 32-bit time_t value.
time_t timeVal = (time_t)INT_MAX + 1;
struct tm tmVal = { 0 };

// Detect whether openssl is using 32-bit or 64-bit time_t.
// If it uses 32-bit time_t, little-endianness means that the pointer
// will be interpreted as a pointer to the lower 32 bits of timeVal.
// tm_year is the number of years since 1900.
if (!OPENSSL_gmtime(&timeVal, &tmVal) || (tmVal.tm_year != 138 && tmVal.tm_year != 1))
{
fprintf(stderr, "Cannot determine the time_t size used by libssl\n");
abort();
}

g_libSslUses32BitTime = (tmVal.tm_year == 1);
#endif
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,6 +187,10 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);

#define API_EXISTS(fn) (fn != NULL)

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
extern bool g_libSslUses32BitTime;
#endif

// List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
// Forgetting to add a function here results in build failure with message reporting the function
// that needs to be added.
Expand DownExpand Up@@ -618,7 +622,6 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);
REQUIRED_FUNCTION(SSL_version) \
FALLBACK_FUNCTION(X509_check_host) \
REQUIRED_FUNCTION(X509_check_purpose) \
REQUIRED_FUNCTION(X509_cmp_current_time) \
REQUIRED_FUNCTION(X509_cmp_time) \
REQUIRED_FUNCTION(X509_CRL_free) \
FALLBACK_FUNCTION(X509_CRL_get0_nextUpdate) \
Expand DownExpand Up@@ -717,7 +720,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr;
#endif
// Redefine all calls to OpenSSL functions as calls through pointers that are set
// to the functions from the libssl.so selected by the shim.
#define a2d_ASN1_OBJECT a2d_ASN1_OBJECT_ptr
Expand DownExpand Up@@ -1018,6 +1023,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define OCSP_RESPONSE_new OCSP_RESPONSE_new_ptr
#define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algorithms_conf_ptr
#define OPENSSL_cleanse OPENSSL_cleanse_ptr
#define OPENSSL_gmtime OPENSSL_gmtime_ptr
#define OPENSSL_init_ssl OPENSSL_init_ssl_ptr
#define OPENSSL_sk_free OPENSSL_sk_free_ptr
#define OPENSSL_sk_new_null OPENSSL_sk_new_null_ptr
Expand DownExpand Up@@ -1149,7 +1155,6 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define TLS_method TLS_method_ptr
#define X509_check_host X509_check_host_ptr
#define X509_check_purpose X509_check_purpose_ptr
#define X509_cmp_current_time X509_cmp_current_time_ptr
#define X509_cmp_time X509_cmp_time_ptr
#define X509_CRL_free X509_CRL_free_ptr
#define X509_CRL_get0_nextUpdate X509_CRL_get0_nextUpdate_ptr
Expand Down
53 changes: 30 additions & 23 deletions src/native/libs/System.Security.Cryptography.Native/pal_x509.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -893,14 +893,12 @@ static OCSP_CERTID* MakeCertId(X509* subject, X509* issuer)
return OCSP_cert_to_id(EVP_sha1(), subject, issuer);
}

static time_t GetIssuanceWindowStart(void)
static time_t GetIssuanceWindowStart(time_t currentTime)
{
// time_t granularity is seconds, so subtract 4 days worth of seconds.
// The 4 day policy is based on the CA/Browser Forum Baseline Requirements
// (version 1.6.3) section 4.9.10 (On-Line Revocation Checking Requirements)
time_t t = time(NULL);
t -= 4 * 24 * 60 * 60;
return t;
return currentTime - 4 * 24 * 60 * 60;
}

static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
Expand DownExpand Up@@ -960,28 +958,37 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,

if (OCSP_resp_find_status(basicResp, certId, &status, NULL, NULL, &thisupd, &nextupd))
{
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
int nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_current_time(nextupd);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else
time_t currentTime = time(NULL);
int nextUpdComparison = 0;
#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
// If openssl uses 32-bit time_t and the current time doesn't fit in 32 bits,
// skip checking the status/nextupd, and fall through to return PAL_X509_V_ERR_UNABLE_TO_GET_CRL.
if (!g_libSslUses32BitTime || (currentTime >= INT_MIN && currentTime <= INT_MAX))
#endif
{
if (nextupd != NULL && nextUpdComparison <= 0)
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_time(nextupd, &currentTime);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
else
{
ret = PAL_X509_V_OK;
if (nextupd != NULL && nextUpdComparison <= 0)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
{
ret = PAL_X509_V_OK;
}
}
}

Expand All@@ -997,7 +1004,7 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
thisupd != NULL &&
nextUpdComparison > 0)
{
time_t oldest = GetIssuanceWindowStart();
time_t oldest = GetIssuanceWindowStart(currentTime);

if (X509_cmp_time(thisupd, &oldest) > 0)
{
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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 numberDiff line numberDiff line change
Expand Up@@ -17,7 +17,7 @@ extends:

containers:
linux_arm:
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0-20240507035943-1390eea
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0
env:
ROOTFS_DIR: /crossrootfs/arm

Expand Down
4 changes: 2 additions & 2 deletions eng/pipelines/coreclr/templates/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -63,9 +63,9 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if eq(variables['System.TeamProject'], 'public') }}:
- (Ubuntu.1804.Arm32.Open)Ubuntu.2004.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- (Ubuntu.1804.Arm32)Ubuntu.2004.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32)Ubuntu.2004.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux arm64
- ${{ if eq(parameters.platform, 'linux_arm64') }}:
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/libraries/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if or(eq(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (Debian.11.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux armv6
- ${{ if eq(parameters.platform, 'linux_armv6') }}:
Expand Down
14 changes: 14 additions & 0 deletions src/native/libs/System.Security.Cryptography.Native/openssl.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -964,6 +964,20 @@ int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx,
return 0;
}

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
if (g_libSslUses32BitTime)
{
if (verifyTime > INT_MAX || verifyTime < INT_MIN)
{
return 0;
}

// Cast to a signature that takes a 32-bit value for the time.
((void (*)(X509_VERIFY_PARAM*, int32_t))(void*)(X509_VERIFY_PARAM_set_time))(verifyParams, (int32_t)verifyTime);
return 1;
}
#endif

X509_VERIFY_PARAM_set_time(verifyParams, verifyTime);
return 1;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,6 +25,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
TYPEOF(OPENSSL_gmtime) OPENSSL_gmtime_ptr;
#endif

// x.x.x, considering the max number of decimal digits for each component
#define MaxVersionStringLength 32
Expand All@@ -41,6 +44,15 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define MAKELIB(v) SONAME_BASE v
#endif

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
Comment thread
sbomer marked this conversation as resolved.
// We support ARM32 linux distros that have Y2038-compatible glibc (those which support _TIME_BITS).
// Some such distros have not yet switched to _TIME_BITS=64 by default, so we may be running against an openssl
// that expects 32-bit time_t even though our time_t is 64-bit.
// This can be deleted once the minimum supported Linux Arm32 distros are
// at least Debian 13 and Ubuntu 24.04.
bool g_libSslUses32BitTime = false;
#endif

static void DlOpen(const char* libraryName)
{
void* libsslNew = dlopen(libraryName, RTLD_LAZY);
Expand DownExpand Up@@ -205,6 +217,10 @@ void InitializeOpenSSLShim(void)
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
if (!(OPENSSL_gmtime_ptr = (TYPEOF(OPENSSL_gmtime))(dlsym(libssl, "OPENSSL_gmtime")))) { fprintf(stderr, "Cannot get required symbol OPENSSL_gmtime from libssl\n"); abort(); }
#endif


// Sanity check that we have at least one functioning way of reporting errors.
if (ERR_put_error_ptr == &local_ERR_put_error)
Expand All@@ -215,4 +231,23 @@ void InitializeOpenSSLShim(void)
abort();
}
}

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
// This value will represent a time in year 2038 if 64-bit time is used,
// or 1901 if the lower 32 bits are interpreted as a 32-bit time_t value.
time_t timeVal = (time_t)INT_MAX + 1;
struct tm tmVal = { 0 };

// Detect whether openssl is using 32-bit or 64-bit time_t.
// If it uses 32-bit time_t, little-endianness means that the pointer
// will be interpreted as a pointer to the lower 32 bits of timeVal.
// tm_year is the number of years since 1900.
if (!OPENSSL_gmtime(&timeVal, &tmVal) || (tmVal.tm_year != 138 && tmVal.tm_year != 1))
{
fprintf(stderr, "Cannot determine the time_t size used by libssl\n");
abort();
}

g_libSslUses32BitTime = (tmVal.tm_year == 1);
#endif
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,6 +187,10 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);

#define API_EXISTS(fn) (fn != NULL)

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
extern bool g_libSslUses32BitTime;
#endif

// List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
// Forgetting to add a function here results in build failure with message reporting the function
// that needs to be added.
Expand DownExpand Up@@ -618,7 +622,6 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);
REQUIRED_FUNCTION(SSL_version) \
FALLBACK_FUNCTION(X509_check_host) \
REQUIRED_FUNCTION(X509_check_purpose) \
REQUIRED_FUNCTION(X509_cmp_current_time) \
REQUIRED_FUNCTION(X509_cmp_time) \
REQUIRED_FUNCTION(X509_CRL_free) \
FALLBACK_FUNCTION(X509_CRL_get0_nextUpdate) \
Expand DownExpand Up@@ -717,7 +720,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr;
#endif
// Redefine all calls to OpenSSL functions as calls through pointers that are set
// to the functions from the libssl.so selected by the shim.
#define a2d_ASN1_OBJECT a2d_ASN1_OBJECT_ptr
Expand DownExpand Up@@ -1018,6 +1023,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define OCSP_RESPONSE_new OCSP_RESPONSE_new_ptr
#define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algorithms_conf_ptr
#define OPENSSL_cleanse OPENSSL_cleanse_ptr
#define OPENSSL_gmtime OPENSSL_gmtime_ptr
#define OPENSSL_init_ssl OPENSSL_init_ssl_ptr
#define OPENSSL_sk_free OPENSSL_sk_free_ptr
#define OPENSSL_sk_new_null OPENSSL_sk_new_null_ptr
Expand DownExpand Up@@ -1149,7 +1155,6 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define TLS_method TLS_method_ptr
#define X509_check_host X509_check_host_ptr
#define X509_check_purpose X509_check_purpose_ptr
#define X509_cmp_current_time X509_cmp_current_time_ptr
#define X509_cmp_time X509_cmp_time_ptr
#define X509_CRL_free X509_CRL_free_ptr
#define X509_CRL_get0_nextUpdate X509_CRL_get0_nextUpdate_ptr
Expand Down
53 changes: 30 additions & 23 deletions src/native/libs/System.Security.Cryptography.Native/pal_x509.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -893,14 +893,12 @@ static OCSP_CERTID* MakeCertId(X509* subject, X509* issuer)
return OCSP_cert_to_id(EVP_sha1(), subject, issuer);
}

static time_t GetIssuanceWindowStart(void)
static time_t GetIssuanceWindowStart(time_t currentTime)
{
// time_t granularity is seconds, so subtract 4 days worth of seconds.
// The 4 day policy is based on the CA/Browser Forum Baseline Requirements
// (version 1.6.3) section 4.9.10 (On-Line Revocation Checking Requirements)
time_t t = time(NULL);
t -= 4 * 24 * 60 * 60;
return t;
return currentTime - 4 * 24 * 60 * 60;
}

static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
Expand DownExpand Up@@ -960,28 +958,37 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,

if (OCSP_resp_find_status(basicResp, certId, &status, NULL, NULL, &thisupd, &nextupd))
{
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
int nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_current_time(nextupd);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else
time_t currentTime = time(NULL);
int nextUpdComparison = 0;
#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
// If openssl uses 32-bit time_t and the current time doesn't fit in 32 bits,
// skip checking the status/nextupd, and fall through to return PAL_X509_V_ERR_UNABLE_TO_GET_CRL.
if (!g_libSslUses32BitTime || (currentTime >= INT_MIN && currentTime <= INT_MAX))
#endif
{
if (nextupd != NULL && nextUpdComparison <= 0)
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_time(nextupd, &currentTime);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
else
{
ret = PAL_X509_V_OK;
if (nextupd != NULL && nextUpdComparison <= 0)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
{
ret = PAL_X509_V_OK;
}
}
}

Expand All@@ -997,7 +1004,7 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
thisupd != NULL &&
nextUpdComparison > 0)
{
time_t oldest = GetIssuanceWindowStart();
time_t oldest = GetIssuanceWindowStart(currentTime);

if (X509_cmp_time(thisupd, &oldest) > 0)
{
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
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 numberDiff line numberDiff line change
Expand Up@@ -17,7 +17,7 @@ extends:

containers:
linux_arm:
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0-20240507035943-1390eea
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0
env:
ROOTFS_DIR: /crossrootfs/arm

Expand Down
4 changes: 2 additions & 2 deletions eng/pipelines/coreclr/templates/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -63,9 +63,9 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if eq(variables['System.TeamProject'], 'public') }}:
- (Ubuntu.1804.Arm32.Open)Ubuntu.2004.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- (Ubuntu.1804.Arm32)Ubuntu.2004.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32)Ubuntu.2004.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux arm64
- ${{ if eq(parameters.platform, 'linux_arm64') }}:
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/libraries/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if or(eq(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (Debian.11.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux armv6
- ${{ if eq(parameters.platform, 'linux_armv6') }}:
Expand Down
14 changes: 14 additions & 0 deletions src/native/libs/System.Security.Cryptography.Native/openssl.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -964,6 +964,20 @@ int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx,
return 0;
}

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
if (g_libSslUses32BitTime)
{
if (verifyTime > INT_MAX || verifyTime < INT_MIN)
{
return 0;
}

// Cast to a signature that takes a 32-bit value for the time.
((void (*)(X509_VERIFY_PARAM*, int32_t))(void*)(X509_VERIFY_PARAM_set_time))(verifyParams, (int32_t)verifyTime);
return 1;
}
#endif

X509_VERIFY_PARAM_set_time(verifyParams, verifyTime);
return 1;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,6 +25,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
TYPEOF(OPENSSL_gmtime) OPENSSL_gmtime_ptr;
#endif

// x.x.x, considering the max number of decimal digits for each component
#define MaxVersionStringLength 32
Expand All@@ -41,6 +44,15 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define MAKELIB(v) SONAME_BASE v
#endif

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
Comment thread
sbomer marked this conversation as resolved.
// We support ARM32 linux distros that have Y2038-compatible glibc (those which support _TIME_BITS).
// Some such distros have not yet switched to _TIME_BITS=64 by default, so we may be running against an openssl
// that expects 32-bit time_t even though our time_t is 64-bit.
// This can be deleted once the minimum supported Linux Arm32 distros are
// at least Debian 13 and Ubuntu 24.04.
bool g_libSslUses32BitTime = false;
#endif

static void DlOpen(const char* libraryName)
{
void* libsslNew = dlopen(libraryName, RTLD_LAZY);
Expand DownExpand Up@@ -205,6 +217,10 @@ void InitializeOpenSSLShim(void)
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
if (!(OPENSSL_gmtime_ptr = (TYPEOF(OPENSSL_gmtime))(dlsym(libssl, "OPENSSL_gmtime")))) { fprintf(stderr, "Cannot get required symbol OPENSSL_gmtime from libssl\n"); abort(); }
#endif


// Sanity check that we have at least one functioning way of reporting errors.
if (ERR_put_error_ptr == &local_ERR_put_error)
Expand All@@ -215,4 +231,23 @@ void InitializeOpenSSLShim(void)
abort();
}
}

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
// This value will represent a time in year 2038 if 64-bit time is used,
// or 1901 if the lower 32 bits are interpreted as a 32-bit time_t value.
time_t timeVal = (time_t)INT_MAX + 1;
struct tm tmVal = { 0 };

// Detect whether openssl is using 32-bit or 64-bit time_t.
// If it uses 32-bit time_t, little-endianness means that the pointer
// will be interpreted as a pointer to the lower 32 bits of timeVal.
// tm_year is the number of years since 1900.
if (!OPENSSL_gmtime(&timeVal, &tmVal) || (tmVal.tm_year != 138 && tmVal.tm_year != 1))
{
fprintf(stderr, "Cannot determine the time_t size used by libssl\n");
abort();
}

g_libSslUses32BitTime = (tmVal.tm_year == 1);
#endif
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,6 +187,10 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);

#define API_EXISTS(fn) (fn != NULL)

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
extern bool g_libSslUses32BitTime;
#endif

// List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
// Forgetting to add a function here results in build failure with message reporting the function
// that needs to be added.
Expand DownExpand Up@@ -618,7 +622,6 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);
REQUIRED_FUNCTION(SSL_version) \
FALLBACK_FUNCTION(X509_check_host) \
REQUIRED_FUNCTION(X509_check_purpose) \
REQUIRED_FUNCTION(X509_cmp_current_time) \
REQUIRED_FUNCTION(X509_cmp_time) \
REQUIRED_FUNCTION(X509_CRL_free) \
FALLBACK_FUNCTION(X509_CRL_get0_nextUpdate) \
Expand DownExpand Up@@ -717,7 +720,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr;
#endif
// Redefine all calls to OpenSSL functions as calls through pointers that are set
// to the functions from the libssl.so selected by the shim.
#define a2d_ASN1_OBJECT a2d_ASN1_OBJECT_ptr
Expand DownExpand Up@@ -1018,6 +1023,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define OCSP_RESPONSE_new OCSP_RESPONSE_new_ptr
#define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algorithms_conf_ptr
#define OPENSSL_cleanse OPENSSL_cleanse_ptr
#define OPENSSL_gmtime OPENSSL_gmtime_ptr
#define OPENSSL_init_ssl OPENSSL_init_ssl_ptr
#define OPENSSL_sk_free OPENSSL_sk_free_ptr
#define OPENSSL_sk_new_null OPENSSL_sk_new_null_ptr
Expand DownExpand Up@@ -1149,7 +1155,6 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define TLS_method TLS_method_ptr
#define X509_check_host X509_check_host_ptr
#define X509_check_purpose X509_check_purpose_ptr
#define X509_cmp_current_time X509_cmp_current_time_ptr
#define X509_cmp_time X509_cmp_time_ptr
#define X509_CRL_free X509_CRL_free_ptr
#define X509_CRL_get0_nextUpdate X509_CRL_get0_nextUpdate_ptr
Expand Down
53 changes: 30 additions & 23 deletions src/native/libs/System.Security.Cryptography.Native/pal_x509.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -893,14 +893,12 @@ static OCSP_CERTID* MakeCertId(X509* subject, X509* issuer)
return OCSP_cert_to_id(EVP_sha1(), subject, issuer);
}

static time_t GetIssuanceWindowStart(void)
static time_t GetIssuanceWindowStart(time_t currentTime)
{
// time_t granularity is seconds, so subtract 4 days worth of seconds.
// The 4 day policy is based on the CA/Browser Forum Baseline Requirements
// (version 1.6.3) section 4.9.10 (On-Line Revocation Checking Requirements)
time_t t = time(NULL);
t -= 4 * 24 * 60 * 60;
return t;
return currentTime - 4 * 24 * 60 * 60;
}

static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
Expand DownExpand Up@@ -960,28 +958,37 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,

if (OCSP_resp_find_status(basicResp, certId, &status, NULL, NULL, &thisupd, &nextupd))
{
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
int nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_current_time(nextupd);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else
time_t currentTime = time(NULL);
int nextUpdComparison = 0;
#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
// If openssl uses 32-bit time_t and the current time doesn't fit in 32 bits,
// skip checking the status/nextupd, and fall through to return PAL_X509_V_ERR_UNABLE_TO_GET_CRL.
if (!g_libSslUses32BitTime || (currentTime >= INT_MIN && currentTime <= INT_MAX))
#endif
{
if (nextupd != NULL && nextUpdComparison <= 0)
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_time(nextupd, &currentTime);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
else
{
ret = PAL_X509_V_OK;
if (nextupd != NULL && nextUpdComparison <= 0)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
{
ret = PAL_X509_V_OK;
}
}
}

Expand All@@ -997,7 +1004,7 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
thisupd != NULL &&
nextUpdComparison > 0)
{
time_t oldest = GetIssuanceWindowStart();
time_t oldest = GetIssuanceWindowStart(currentTime);

if (X509_cmp_time(thisupd, &oldest) > 0)
{
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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 numberDiff line numberDiff line change
Expand Up@@ -17,7 +17,7 @@ extends:

containers:
linux_arm:
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0-20240507035943-1390eea
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0
env:
ROOTFS_DIR: /crossrootfs/arm

Expand Down
4 changes: 2 additions & 2 deletions eng/pipelines/coreclr/templates/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -63,9 +63,9 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if eq(variables['System.TeamProject'], 'public') }}:
- (Ubuntu.1804.Arm32.Open)Ubuntu.2004.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- (Ubuntu.1804.Arm32)Ubuntu.2004.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32)Ubuntu.2004.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux arm64
- ${{ if eq(parameters.platform, 'linux_arm64') }}:
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/libraries/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if or(eq(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (Debian.11.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux armv6
- ${{ if eq(parameters.platform, 'linux_armv6') }}:
Expand Down
14 changes: 14 additions & 0 deletions src/native/libs/System.Security.Cryptography.Native/openssl.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -964,6 +964,20 @@ int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx,
return 0;
}

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
if (g_libSslUses32BitTime)
{
if (verifyTime > INT_MAX || verifyTime < INT_MIN)
{
return 0;
}

// Cast to a signature that takes a 32-bit value for the time.
((void (*)(X509_VERIFY_PARAM*, int32_t))(void*)(X509_VERIFY_PARAM_set_time))(verifyParams, (int32_t)verifyTime);
return 1;
}
#endif

X509_VERIFY_PARAM_set_time(verifyParams, verifyTime);
return 1;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,6 +25,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
TYPEOF(OPENSSL_gmtime) OPENSSL_gmtime_ptr;
#endif

// x.x.x, considering the max number of decimal digits for each component
#define MaxVersionStringLength 32
Expand All@@ -41,6 +44,15 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define MAKELIB(v) SONAME_BASE v
#endif

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
Comment thread
sbomer marked this conversation as resolved.
// We support ARM32 linux distros that have Y2038-compatible glibc (those which support _TIME_BITS).
// Some such distros have not yet switched to _TIME_BITS=64 by default, so we may be running against an openssl
// that expects 32-bit time_t even though our time_t is 64-bit.
// This can be deleted once the minimum supported Linux Arm32 distros are
// at least Debian 13 and Ubuntu 24.04.
bool g_libSslUses32BitTime = false;
#endif

static void DlOpen(const char* libraryName)
{
void* libsslNew = dlopen(libraryName, RTLD_LAZY);
Expand DownExpand Up@@ -205,6 +217,10 @@ void InitializeOpenSSLShim(void)
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
if (!(OPENSSL_gmtime_ptr = (TYPEOF(OPENSSL_gmtime))(dlsym(libssl, "OPENSSL_gmtime")))) { fprintf(stderr, "Cannot get required symbol OPENSSL_gmtime from libssl\n"); abort(); }
#endif


// Sanity check that we have at least one functioning way of reporting errors.
if (ERR_put_error_ptr == &local_ERR_put_error)
Expand All@@ -215,4 +231,23 @@ void InitializeOpenSSLShim(void)
abort();
}
}

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
// This value will represent a time in year 2038 if 64-bit time is used,
// or 1901 if the lower 32 bits are interpreted as a 32-bit time_t value.
time_t timeVal = (time_t)INT_MAX + 1;
struct tm tmVal = { 0 };

// Detect whether openssl is using 32-bit or 64-bit time_t.
// If it uses 32-bit time_t, little-endianness means that the pointer
// will be interpreted as a pointer to the lower 32 bits of timeVal.
// tm_year is the number of years since 1900.
if (!OPENSSL_gmtime(&timeVal, &tmVal) || (tmVal.tm_year != 138 && tmVal.tm_year != 1))
{
fprintf(stderr, "Cannot determine the time_t size used by libssl\n");
abort();
}

g_libSslUses32BitTime = (tmVal.tm_year == 1);
#endif
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,6 +187,10 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);

#define API_EXISTS(fn) (fn != NULL)

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
extern bool g_libSslUses32BitTime;
#endif

// List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
// Forgetting to add a function here results in build failure with message reporting the function
// that needs to be added.
Expand DownExpand Up@@ -618,7 +622,6 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);
REQUIRED_FUNCTION(SSL_version) \
FALLBACK_FUNCTION(X509_check_host) \
REQUIRED_FUNCTION(X509_check_purpose) \
REQUIRED_FUNCTION(X509_cmp_current_time) \
REQUIRED_FUNCTION(X509_cmp_time) \
REQUIRED_FUNCTION(X509_CRL_free) \
FALLBACK_FUNCTION(X509_CRL_get0_nextUpdate) \
Expand DownExpand Up@@ -717,7 +720,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr;
#endif
// Redefine all calls to OpenSSL functions as calls through pointers that are set
// to the functions from the libssl.so selected by the shim.
#define a2d_ASN1_OBJECT a2d_ASN1_OBJECT_ptr
Expand DownExpand Up@@ -1018,6 +1023,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define OCSP_RESPONSE_new OCSP_RESPONSE_new_ptr
#define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algorithms_conf_ptr
#define OPENSSL_cleanse OPENSSL_cleanse_ptr
#define OPENSSL_gmtime OPENSSL_gmtime_ptr
#define OPENSSL_init_ssl OPENSSL_init_ssl_ptr
#define OPENSSL_sk_free OPENSSL_sk_free_ptr
#define OPENSSL_sk_new_null OPENSSL_sk_new_null_ptr
Expand DownExpand Up@@ -1149,7 +1155,6 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define TLS_method TLS_method_ptr
#define X509_check_host X509_check_host_ptr
#define X509_check_purpose X509_check_purpose_ptr
#define X509_cmp_current_time X509_cmp_current_time_ptr
#define X509_cmp_time X509_cmp_time_ptr
#define X509_CRL_free X509_CRL_free_ptr
#define X509_CRL_get0_nextUpdate X509_CRL_get0_nextUpdate_ptr
Expand Down
53 changes: 30 additions & 23 deletions src/native/libs/System.Security.Cryptography.Native/pal_x509.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -893,14 +893,12 @@ static OCSP_CERTID* MakeCertId(X509* subject, X509* issuer)
return OCSP_cert_to_id(EVP_sha1(), subject, issuer);
}

static time_t GetIssuanceWindowStart(void)
static time_t GetIssuanceWindowStart(time_t currentTime)
{
// time_t granularity is seconds, so subtract 4 days worth of seconds.
// The 4 day policy is based on the CA/Browser Forum Baseline Requirements
// (version 1.6.3) section 4.9.10 (On-Line Revocation Checking Requirements)
time_t t = time(NULL);
t -= 4 * 24 * 60 * 60;
return t;
return currentTime - 4 * 24 * 60 * 60;
}

static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
Expand DownExpand Up@@ -960,28 +958,37 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,

if (OCSP_resp_find_status(basicResp, certId, &status, NULL, NULL, &thisupd, &nextupd))
{
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
int nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_current_time(nextupd);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else
time_t currentTime = time(NULL);
int nextUpdComparison = 0;
#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
// If openssl uses 32-bit time_t and the current time doesn't fit in 32 bits,
// skip checking the status/nextupd, and fall through to return PAL_X509_V_ERR_UNABLE_TO_GET_CRL.
if (!g_libSslUses32BitTime || (currentTime >= INT_MIN && currentTime <= INT_MAX))
#endif
{
if (nextupd != NULL && nextUpdComparison <= 0)
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_time(nextupd, &currentTime);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
else
{
ret = PAL_X509_V_OK;
if (nextupd != NULL && nextUpdComparison <= 0)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
{
ret = PAL_X509_V_OK;
}
}
}

Expand All@@ -997,7 +1004,7 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
thisupd != NULL &&
nextUpdComparison > 0)
{
time_t oldest = GetIssuanceWindowStart();
time_t oldest = GetIssuanceWindowStart(currentTime);

if (X509_cmp_time(thisupd, &oldest) > 0)
{
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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 numberDiff line numberDiff line change
Expand Up@@ -17,7 +17,7 @@ extends:

containers:
linux_arm:
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0-20240507035943-1390eea
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0
env:
ROOTFS_DIR: /crossrootfs/arm

Expand Down
4 changes: 2 additions & 2 deletions eng/pipelines/coreclr/templates/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -63,9 +63,9 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if eq(variables['System.TeamProject'], 'public') }}:
- (Ubuntu.1804.Arm32.Open)Ubuntu.2004.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- (Ubuntu.1804.Arm32)Ubuntu.2004.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32)Ubuntu.2004.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux arm64
- ${{ if eq(parameters.platform, 'linux_arm64') }}:
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/libraries/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if or(eq(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (Debian.11.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux armv6
- ${{ if eq(parameters.platform, 'linux_armv6') }}:
Expand Down
14 changes: 14 additions & 0 deletions src/native/libs/System.Security.Cryptography.Native/openssl.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -964,6 +964,20 @@ int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx,
return 0;
}

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
if (g_libSslUses32BitTime)
{
if (verifyTime > INT_MAX || verifyTime < INT_MIN)
{
return 0;
}

// Cast to a signature that takes a 32-bit value for the time.
((void (*)(X509_VERIFY_PARAM*, int32_t))(void*)(X509_VERIFY_PARAM_set_time))(verifyParams, (int32_t)verifyTime);
return 1;
}
#endif

X509_VERIFY_PARAM_set_time(verifyParams, verifyTime);
return 1;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,6 +25,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
TYPEOF(OPENSSL_gmtime) OPENSSL_gmtime_ptr;
#endif

// x.x.x, considering the max number of decimal digits for each component
#define MaxVersionStringLength 32
Expand All@@ -41,6 +44,15 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define MAKELIB(v) SONAME_BASE v
#endif

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
Comment thread
sbomer marked this conversation as resolved.
// We support ARM32 linux distros that have Y2038-compatible glibc (those which support _TIME_BITS).
// Some such distros have not yet switched to _TIME_BITS=64 by default, so we may be running against an openssl
// that expects 32-bit time_t even though our time_t is 64-bit.
// This can be deleted once the minimum supported Linux Arm32 distros are
// at least Debian 13 and Ubuntu 24.04.
bool g_libSslUses32BitTime = false;
#endif

static void DlOpen(const char* libraryName)
{
void* libsslNew = dlopen(libraryName, RTLD_LAZY);
Expand DownExpand Up@@ -205,6 +217,10 @@ void InitializeOpenSSLShim(void)
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
if (!(OPENSSL_gmtime_ptr = (TYPEOF(OPENSSL_gmtime))(dlsym(libssl, "OPENSSL_gmtime")))) { fprintf(stderr, "Cannot get required symbol OPENSSL_gmtime from libssl\n"); abort(); }
#endif


// Sanity check that we have at least one functioning way of reporting errors.
if (ERR_put_error_ptr == &local_ERR_put_error)
Expand All@@ -215,4 +231,23 @@ void InitializeOpenSSLShim(void)
abort();
}
}

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
// This value will represent a time in year 2038 if 64-bit time is used,
// or 1901 if the lower 32 bits are interpreted as a 32-bit time_t value.
time_t timeVal = (time_t)INT_MAX + 1;
struct tm tmVal = { 0 };

// Detect whether openssl is using 32-bit or 64-bit time_t.
// If it uses 32-bit time_t, little-endianness means that the pointer
// will be interpreted as a pointer to the lower 32 bits of timeVal.
// tm_year is the number of years since 1900.
if (!OPENSSL_gmtime(&timeVal, &tmVal) || (tmVal.tm_year != 138 && tmVal.tm_year != 1))
{
fprintf(stderr, "Cannot determine the time_t size used by libssl\n");
abort();
}

g_libSslUses32BitTime = (tmVal.tm_year == 1);
#endif
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,6 +187,10 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);

#define API_EXISTS(fn) (fn != NULL)

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
extern bool g_libSslUses32BitTime;
#endif

// List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
// Forgetting to add a function here results in build failure with message reporting the function
// that needs to be added.
Expand DownExpand Up@@ -618,7 +622,6 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);
REQUIRED_FUNCTION(SSL_version) \
FALLBACK_FUNCTION(X509_check_host) \
REQUIRED_FUNCTION(X509_check_purpose) \
REQUIRED_FUNCTION(X509_cmp_current_time) \
REQUIRED_FUNCTION(X509_cmp_time) \
REQUIRED_FUNCTION(X509_CRL_free) \
FALLBACK_FUNCTION(X509_CRL_get0_nextUpdate) \
Expand DownExpand Up@@ -717,7 +720,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr;
#endif
// Redefine all calls to OpenSSL functions as calls through pointers that are set
// to the functions from the libssl.so selected by the shim.
#define a2d_ASN1_OBJECT a2d_ASN1_OBJECT_ptr
Expand DownExpand Up@@ -1018,6 +1023,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define OCSP_RESPONSE_new OCSP_RESPONSE_new_ptr
#define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algorithms_conf_ptr
#define OPENSSL_cleanse OPENSSL_cleanse_ptr
#define OPENSSL_gmtime OPENSSL_gmtime_ptr
#define OPENSSL_init_ssl OPENSSL_init_ssl_ptr
#define OPENSSL_sk_free OPENSSL_sk_free_ptr
#define OPENSSL_sk_new_null OPENSSL_sk_new_null_ptr
Expand DownExpand Up@@ -1149,7 +1155,6 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define TLS_method TLS_method_ptr
#define X509_check_host X509_check_host_ptr
#define X509_check_purpose X509_check_purpose_ptr
#define X509_cmp_current_time X509_cmp_current_time_ptr
#define X509_cmp_time X509_cmp_time_ptr
#define X509_CRL_free X509_CRL_free_ptr
#define X509_CRL_get0_nextUpdate X509_CRL_get0_nextUpdate_ptr
Expand Down
53 changes: 30 additions & 23 deletions src/native/libs/System.Security.Cryptography.Native/pal_x509.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -893,14 +893,12 @@ static OCSP_CERTID* MakeCertId(X509* subject, X509* issuer)
return OCSP_cert_to_id(EVP_sha1(), subject, issuer);
}

static time_t GetIssuanceWindowStart(void)
static time_t GetIssuanceWindowStart(time_t currentTime)
{
// time_t granularity is seconds, so subtract 4 days worth of seconds.
// The 4 day policy is based on the CA/Browser Forum Baseline Requirements
// (version 1.6.3) section 4.9.10 (On-Line Revocation Checking Requirements)
time_t t = time(NULL);
t -= 4 * 24 * 60 * 60;
return t;
return currentTime - 4 * 24 * 60 * 60;
}

static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
Expand DownExpand Up@@ -960,28 +958,37 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,

if (OCSP_resp_find_status(basicResp, certId, &status, NULL, NULL, &thisupd, &nextupd))
{
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
int nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_current_time(nextupd);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else
time_t currentTime = time(NULL);
int nextUpdComparison = 0;
#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
// If openssl uses 32-bit time_t and the current time doesn't fit in 32 bits,
// skip checking the status/nextupd, and fall through to return PAL_X509_V_ERR_UNABLE_TO_GET_CRL.
if (!g_libSslUses32BitTime || (currentTime >= INT_MIN && currentTime <= INT_MAX))
#endif
{
if (nextupd != NULL && nextUpdComparison <= 0)
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_time(nextupd, &currentTime);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
else
{
ret = PAL_X509_V_OK;
if (nextupd != NULL && nextUpdComparison <= 0)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
{
ret = PAL_X509_V_OK;
}
}
}

Expand All@@ -997,7 +1004,7 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
thisupd != NULL &&
nextUpdComparison > 0)
{
time_t oldest = GetIssuanceWindowStart();
time_t oldest = GetIssuanceWindowStart(currentTime);

if (X509_cmp_time(thisupd, &oldest) > 0)
{
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
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 numberDiff line numberDiff line change
Expand Up@@ -17,7 +17,7 @@ extends:

containers:
linux_arm:
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0-20240507035943-1390eea
image: mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-cross-arm-net9.0
env:
ROOTFS_DIR: /crossrootfs/arm

Expand Down
4 changes: 2 additions & 2 deletions eng/pipelines/coreclr/templates/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -63,9 +63,9 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if eq(variables['System.TeamProject'], 'public') }}:
- (Ubuntu.1804.Arm32.Open)Ubuntu.2004.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- (Ubuntu.1804.Arm32)Ubuntu.2004.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7
- (Debian.12.Arm32)Ubuntu.2004.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux arm64
- ${{ if eq(parameters.platform, 'linux_arm64') }}:
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/libraries/helix-queues-setup.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'linux_arm') }}:
- ${{ if or(eq(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (Debian.11.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7
- (Debian.12.Arm32.Open)Ubuntu.2004.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-arm32v7

# Linux armv6
- ${{ if eq(parameters.platform, 'linux_armv6') }}:
Expand Down
14 changes: 14 additions & 0 deletions src/native/libs/System.Security.Cryptography.Native/openssl.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -964,6 +964,20 @@ int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx,
return 0;
}

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
if (g_libSslUses32BitTime)
{
if (verifyTime > INT_MAX || verifyTime < INT_MIN)
{
return 0;
}

// Cast to a signature that takes a 32-bit value for the time.
((void (*)(X509_VERIFY_PARAM*, int32_t))(void*)(X509_VERIFY_PARAM_set_time))(verifyParams, (int32_t)verifyTime);
return 1;
}
#endif

X509_VERIFY_PARAM_set_time(verifyParams, verifyTime);
return 1;
}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,6 +25,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
TYPEOF(OPENSSL_gmtime) OPENSSL_gmtime_ptr;
#endif

// x.x.x, considering the max number of decimal digits for each component
#define MaxVersionStringLength 32
Expand All@@ -41,6 +44,15 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define MAKELIB(v) SONAME_BASE v
#endif

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
Comment thread
sbomer marked this conversation as resolved.
// We support ARM32 linux distros that have Y2038-compatible glibc (those which support _TIME_BITS).
// Some such distros have not yet switched to _TIME_BITS=64 by default, so we may be running against an openssl
// that expects 32-bit time_t even though our time_t is 64-bit.
// This can be deleted once the minimum supported Linux Arm32 distros are
// at least Debian 13 and Ubuntu 24.04.
bool g_libSslUses32BitTime = false;
#endif

static void DlOpen(const char* libraryName)
{
void* libsslNew = dlopen(libraryName, RTLD_LAZY);
Expand DownExpand Up@@ -205,6 +217,10 @@ void InitializeOpenSSLShim(void)
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION
#if defined(TARGET_ARM) && defined(TARGET_LINUX)
if (!(OPENSSL_gmtime_ptr = (TYPEOF(OPENSSL_gmtime))(dlsym(libssl, "OPENSSL_gmtime")))) { fprintf(stderr, "Cannot get required symbol OPENSSL_gmtime from libssl\n"); abort(); }
#endif


// Sanity check that we have at least one functioning way of reporting errors.
if (ERR_put_error_ptr == &local_ERR_put_error)
Expand All@@ -215,4 +231,23 @@ void InitializeOpenSSLShim(void)
abort();
}
}

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
// This value will represent a time in year 2038 if 64-bit time is used,
// or 1901 if the lower 32 bits are interpreted as a 32-bit time_t value.
time_t timeVal = (time_t)INT_MAX + 1;
struct tm tmVal = { 0 };

// Detect whether openssl is using 32-bit or 64-bit time_t.
// If it uses 32-bit time_t, little-endianness means that the pointer
// will be interpreted as a pointer to the lower 32 bits of timeVal.
// tm_year is the number of years since 1900.
if (!OPENSSL_gmtime(&timeVal, &tmVal) || (tmVal.tm_year != 138 && tmVal.tm_year != 1))
{
fprintf(stderr, "Cannot determine the time_t size used by libssl\n");
abort();
}

g_libSslUses32BitTime = (tmVal.tm_year == 1);
#endif
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,6 +187,10 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);

#define API_EXISTS(fn) (fn != NULL)

#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
extern bool g_libSslUses32BitTime;
#endif

// List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
// Forgetting to add a function here results in build failure with message reporting the function
// that needs to be added.
Expand DownExpand Up@@ -618,7 +622,6 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);
REQUIRED_FUNCTION(SSL_version) \
FALLBACK_FUNCTION(X509_check_host) \
REQUIRED_FUNCTION(X509_check_purpose) \
REQUIRED_FUNCTION(X509_cmp_current_time) \
REQUIRED_FUNCTION(X509_cmp_time) \
REQUIRED_FUNCTION(X509_CRL_free) \
FALLBACK_FUNCTION(X509_CRL_get0_nextUpdate) \
Expand DownExpand Up@@ -717,7 +720,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
#undef LIGHTUP_FUNCTION
#undef REQUIRED_FUNCTION_110
#undef REQUIRED_FUNCTION

#if defined(TARGET_ARM) && defined(TARGET_LINUX)
extern TYPEOF(OPENSSL_gmtime)* OPENSSL_gmtime_ptr;
#endif
// Redefine all calls to OpenSSL functions as calls through pointers that are set
// to the functions from the libssl.so selected by the shim.
#define a2d_ASN1_OBJECT a2d_ASN1_OBJECT_ptr
Expand DownExpand Up@@ -1018,6 +1023,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define OCSP_RESPONSE_new OCSP_RESPONSE_new_ptr
#define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algorithms_conf_ptr
#define OPENSSL_cleanse OPENSSL_cleanse_ptr
#define OPENSSL_gmtime OPENSSL_gmtime_ptr
#define OPENSSL_init_ssl OPENSSL_init_ssl_ptr
#define OPENSSL_sk_free OPENSSL_sk_free_ptr
#define OPENSSL_sk_new_null OPENSSL_sk_new_null_ptr
Expand DownExpand Up@@ -1149,7 +1155,6 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define TLS_method TLS_method_ptr
#define X509_check_host X509_check_host_ptr
#define X509_check_purpose X509_check_purpose_ptr
#define X509_cmp_current_time X509_cmp_current_time_ptr
#define X509_cmp_time X509_cmp_time_ptr
#define X509_CRL_free X509_CRL_free_ptr
#define X509_CRL_get0_nextUpdate X509_CRL_get0_nextUpdate_ptr
Expand Down
53 changes: 30 additions & 23 deletions src/native/libs/System.Security.Cryptography.Native/pal_x509.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -893,14 +893,12 @@ static OCSP_CERTID* MakeCertId(X509* subject, X509* issuer)
return OCSP_cert_to_id(EVP_sha1(), subject, issuer);
}

static time_t GetIssuanceWindowStart(void)
static time_t GetIssuanceWindowStart(time_t currentTime)
{
// time_t granularity is seconds, so subtract 4 days worth of seconds.
// The 4 day policy is based on the CA/Browser Forum Baseline Requirements
// (version 1.6.3) section 4.9.10 (On-Line Revocation Checking Requirements)
time_t t = time(NULL);
t -= 4 * 24 * 60 * 60;
return t;
return currentTime - 4 * 24 * 60 * 60;
}

static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
Expand DownExpand Up@@ -960,28 +958,37 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,

if (OCSP_resp_find_status(basicResp, certId, &status, NULL, NULL, &thisupd, &nextupd))
{
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
int nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_current_time(nextupd);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else
time_t currentTime = time(NULL);
int nextUpdComparison = 0;
#if defined(FEATURE_DISTRO_AGNOSTIC_SSL) && defined(TARGET_ARM) && defined(TARGET_LINUX)
// If openssl uses 32-bit time_t and the current time doesn't fit in 32 bits,
// skip checking the status/nextupd, and fall through to return PAL_X509_V_ERR_UNABLE_TO_GET_CRL.
if (!g_libSslUses32BitTime || (currentTime >= INT_MIN && currentTime <= INT_MAX))
#endif
{
if (nextupd != NULL && nextUpdComparison <= 0)
// X509_cmp_current_time uses 0 for error already, so we can use it when there's a null value.
// 1 means the nextupd value is in the future, -1 means it is now-or-in-the-past.
// Following with OpenSSL conventions, we'll accept "now" as "the past".
nextUpdComparison = nextupd == NULL ? 0 : X509_cmp_time(nextupd, &currentTime);

// Un-revoking is rare, so reporting revoked on an expired response has a low chance
// of a false-positive.
//
// For non-revoked responses, a next-update value in the past counts as expired.
if (status == V_OCSP_CERTSTATUS_REVOKED)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
ret = PAL_X509_V_ERR_CERT_REVOKED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
else
{
ret = PAL_X509_V_OK;
if (nextupd != NULL && nextUpdComparison <= 0)
{
ret = PAL_X509_V_ERR_CRL_HAS_EXPIRED;
}
else if (status == V_OCSP_CERTSTATUS_GOOD)
{
ret = PAL_X509_V_OK;
}
}
}

Expand All@@ -997,7 +1004,7 @@ static X509VerifyStatusCode CheckOcspGetExpiry(OCSP_REQUEST* req,
thisupd != NULL &&
nextUpdComparison > 0)
{
time_t oldest = GetIssuanceWindowStart();
time_t oldest = GetIssuanceWindowStart(currentTime);

if (X509_cmp_time(thisupd, &oldest) > 0)
{
Expand Down