From 8f512dba7a1236e333961e3a8e9a32583948b50b Mon Sep 17 00:00:00 2001 From: Koen van Leeuwen Date: Sun, 14 Jun 2026 11:54:11 +0200 Subject: [PATCH 1/5] Add regression tests for #109039 (chain time validity vs mid-process TZ change) Linux-only tests (RemoteExecutor + TZ) covering both directions of the OpenSSL chain verification-time bug, as a theory over Kind=Utc and Kind=Local verify times: a valid certificate must stay time-valid, and an expired certificate must stay NotTimeValid, across a mid-process time-zone change. Co-Authored-By: Claude Opus 4.8 --- .../System.Security.Cryptography.Tests.csproj | 1 + .../ChainTests.TimeZone.Linux.cs | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs diff --git a/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj b/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj index f490702df59f7b..49d9d0403c5225 100644 --- a/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj +++ b/src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj @@ -631,6 +631,7 @@ + diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs new file mode 100644 index 00000000000000..cd740e41843b06 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs @@ -0,0 +1,98 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.RemoteExecutor; +using Xunit; + +namespace System.Security.Cryptography.X509Certificates.Tests +{ + // Chain time validity must not depend on the process time zone. + // https://github.com/dotnet/runtime/issues/109039 + // OpenSSL/Linux only (Windows/macOS convert the verify time correctly). + // RemoteExecutor + TZ isolates the time-zone change to a child process. + [PlatformSpecific(TestPlatforms.Linux)] + public static class ChainTimeZoneTests + { + private static readonly DateTimeOffset s_verify = new(2024, 6, 15, 12, 0, 0, TimeSpan.Zero); + + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [InlineData(false)] + [InlineData(true)] + public static void ValidCert_StaysTimeValidAfterTimeZoneChange(bool asLocal) + { + RemoteExecutor.Invoke(static asLocalStr => + { + // Validity margin (+/-2h) is narrower than the UTC+14 shift below, so the + // bug (if present) moves the effective verify time outside the window. + using X509Certificate2 cert = ChainTimeZone.MakeCert(s_verify.AddHours(-2), s_verify.AddHours(2)); + bool asLocal = bool.Parse(asLocalStr); + + ChainTimeZone.SetZone("UTC"); + Assert.True(ChainTimeZone.IsTimeValid(cert, s_verify, asLocal)); + + ChainTimeZone.SetZone("Pacific/Kiritimati"); // UTC+14 + Assert.True(ChainTimeZone.IsTimeValid(cert, s_verify, asLocal)); + }, asLocal.ToString()).Dispose(); + } + } + + // Companion to ChainTimeZoneTests: the opposite-sign case, an expired + // certificate must not become time-valid after a westward time-zone change. + // https://github.com/dotnet/runtime/issues/109039 + [PlatformSpecific(TestPlatforms.Linux)] + public static class ChainTimeZoneExpiredTests + { + private static readonly DateTimeOffset s_verify = new(2024, 6, 15, 12, 0, 0, TimeSpan.Zero); + + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [InlineData(false)] + [InlineData(true)] + public static void ExpiredCert_StaysNotTimeValidAfterTimeZoneChange(bool asLocal) + { + RemoteExecutor.Invoke(static asLocalStr => + { + // Expired 30 min before s_verify. NotBefore is >14h earlier so the + // westward shift (~14h) lands back inside the window (re-entering + // validity from the expiry side), not before NotBefore. + using X509Certificate2 cert = ChainTimeZone.MakeCert(s_verify.AddHours(-20), s_verify.AddMinutes(-30)); + bool asLocal = bool.Parse(asLocalStr); + + ChainTimeZone.SetZone("Pacific/Kiritimati"); // UTC+14 + Assert.False(ChainTimeZone.IsTimeValid(cert, s_verify, asLocal)); + + ChainTimeZone.SetZone("UTC"); // westward: "now" moves back ~14h + Assert.False(ChainTimeZone.IsTimeValid(cert, s_verify, asLocal)); + }, asLocal.ToString()).Dispose(); + } + } + + internal static class ChainTimeZone + { + internal static void SetZone(string tz) + { + Environment.SetEnvironmentVariable("TZ", tz); + TimeZoneInfo.ClearCachedData(); // required to reproduce #109039: refresh the cached local zone + } + + internal static X509Certificate2 MakeCert(DateTimeOffset notBefore, DateTimeOffset notAfter) + { + using RSA key = RSA.Create(2048); + var req = new CertificateRequest("CN=109039", key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + return req.CreateSelfSigned(notBefore, notAfter); + } + + // Verify-time source (Utc vs Local) must not change the verdict. + internal static bool IsTimeValid(X509Certificate2 cert, DateTimeOffset verify, bool asLocal) + { + using ChainHolder holder = new(); + X509Chain chain = holder.Chain; + chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; + chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; + chain.ChainPolicy.CustomTrustStore.Add(cert); + chain.ChainPolicy.VerificationTime = asLocal ? verify.LocalDateTime : verify.UtcDateTime; + + chain.Build(cert); + return (chain.AllStatusFlags() & X509ChainStatusFlags.NotTimeValid) == 0; + } + } +} From 3c60e1ce6697d236fc1699f8830e6195c7e8d7a1 Mon Sep 17 00:00:00 2001 From: Koen van Leeuwen Date: Sun, 14 Jun 2026 11:54:12 +0200 Subject: [PATCH 2/5] Fix #109039: carry chain verification time to OpenSSL as UTC The OpenSSL chain backend passed the verification time to native code as broken-down local fields and reconstructed it with mktime(), which re-resolves them against the process's current time zone. Because a certificate's validity window is a fixed UTC instant, a mid-process time-zone change shifted the effective verification instant and could flip the time-validity verdict (a valid cert reported NotTimeValid, or an expired cert no longer reported NotTimeValid). X509_VERIFY_PARAM_set_time takes a time_t (UTC epoch seconds), so the local round-trip was unnecessary. Pass the verification time as a UTC Unix timestamp: - Interop X509StoreSetVerifyTime now takes DateTimeOffset -> ToUnixTimeSeconds(). - CryptoNative_X509StoreSetVerifyTime takes int64_t and forwards it straight to X509_VERIFY_PARAM_set_time; MakeTimeT/mktime removed. The 32-bit time_t ARM guard is preserved. - The OpenSSL chain processor carries the verification time as a DateTimeOffset. Internal + native only; X509ChainPolicy.VerificationTime stays a public DateTime. Co-Authored-By: Claude Opus 4.8 --- .../Interop.Crypto.cs | 24 ++-------- .../X509Certificates/ChainPal.OpenSsl.cs | 13 ++---- .../OpenSslX509ChainProcessor.cs | 8 ++-- .../openssl.c | 46 ++----------------- .../openssl.h | 9 +--- 5 files changed, 17 insertions(+), 83 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs index a451e0d9e918e3..2fef48465370d2 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs @@ -90,13 +90,7 @@ internal static int BioTell(SafeBioHandle bio) [LibraryImport(Libraries.CryptoNative)] private static partial int CryptoNative_X509StoreSetVerifyTime( SafeX509StoreHandle ctx, - int year, - int month, - int day, - int hour, - int minute, - int second, - [MarshalAs(UnmanagedType.Bool)] bool isDst); + long unixTime); [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_CheckX509IpAddress", StringMarshalling = StringMarshalling.Utf8)] internal static partial int CheckX509IpAddress(SafeX509Handle x509, byte[] addressBytes, int addressLen, string hostname, int cchHostname); @@ -150,21 +144,9 @@ internal static X500DistinguishedName LoadX500Name(IntPtr namePtr) return GetNullableDynamicBuffer(GetX509PublicKeyParameterBytes, x509); } - internal static void X509StoreSetVerifyTime(SafeX509StoreHandle ctx, DateTime verifyTime) + internal static void X509StoreSetVerifyTime(SafeX509StoreHandle ctx, DateTimeOffset verifyTime) { - // OpenSSL is going to convert our input time to universal, so we should be in Local or - // Unspecified (local-assumed). - Debug.Assert(verifyTime.Kind != DateTimeKind.Utc, "UTC verifyTime should have been normalized to Local"); - - int succeeded = CryptoNative_X509StoreSetVerifyTime( - ctx, - verifyTime.Year, - verifyTime.Month, - verifyTime.Day, - verifyTime.Hour, - verifyTime.Minute, - verifyTime.Second, - verifyTime.IsDaylightSavingTime()); + int succeeded = CryptoNative_X509StoreSetVerifyTime(ctx, verifyTime.ToUnixTimeSeconds()); if (succeeded != 1) { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs index 2c034f6d1b4b26..61bebd8d8a4b55 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs @@ -98,14 +98,9 @@ public static void FlushStores() timeout = s_maxUrlRetrievalTimeout; } - // Let Unspecified mean Local, so only convert if the source was UTC. - // - // Converge on Local instead of UTC because OpenSSL is going to assume we gave it - // local time. - if (verificationTime.Kind == DateTimeKind.Utc) - { - verificationTime = verificationTime.ToLocalTime(); - } + // Convert to an absolute instant for OpenSSL. + // (https://github.com/dotnet/runtime/issues/109039). + var verificationInstant = new DateTimeOffset(verificationTime); // Until we support the Disallowed store, ensure it's empty (which is done by the ctor) using (new X509Store(StoreName.Disallowed, StoreLocation.CurrentUser, OpenFlags.ReadOnly)) @@ -118,7 +113,7 @@ public static void FlushStores() ((OpenSslX509CertificateReader)cert).SafeHandle, customTrustStore, trustMode, - verificationTime, + verificationInstant, downloadTimeout); Interop.Crypto.X509VerifyStatusCode status = chainPal.FindFirstChain(extraStore); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs index a9883b74b2aff7..13c437617b5a36 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509ChainProcessor.cs @@ -46,7 +46,7 @@ internal sealed class OpenSslX509ChainProcessor : IChainPal private SafeX509StoreHandle _store; private readonly SafeX509StackHandle _untrustedLookup; private readonly SafeX509StoreCtxHandle _storeCtx; - private readonly DateTime _verificationTime; + private readonly DateTimeOffset _verificationTime; private readonly TimeSpan _downloadTimeout; private WorkingChain? _workingChain; @@ -55,7 +55,7 @@ private OpenSslX509ChainProcessor( SafeX509StoreHandle store, SafeX509StackHandle untrusted, SafeX509StoreCtxHandle storeCtx, - DateTime verificationTime, + DateTimeOffset verificationTime, TimeSpan downloadTimeout) { _leafHandle = leafHandle; @@ -95,7 +95,7 @@ internal static OpenSslX509ChainProcessor InitiateChain( SafeX509Handle leafHandle, X509Certificate2Collection? customTrustStore, X509ChainTrustMode trustMode, - DateTime verificationTime, + DateTimeOffset verificationTime, TimeSpan remainingDownloadTime) { OpenSslCachedSystemStoreProvider.GetNativeCollections( @@ -401,7 +401,7 @@ internal void ProcessRevocation( cert, _store, revocationMode, - _verificationTime, + _verificationTime.LocalDateTime, _downloadTimeout); } } diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index 1b80f0bb03407c..4e366d90d5a1e4 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -38,31 +38,6 @@ c_static_assert(CRYPTO_EX_INDEX_SSL_SESSION == 2); // See X509NameType.UrlName #define NAME_TYPE_URL 5 -/* -Function: -MakeTimeT - -Used to convert the constituent elements of a struct tm into a time_t. As time_t does not have -a guaranteed blitting size, this function is static and cannot be p/invoked. It is here merely -as a utility. - -Return values: -A time_t representation of the input date. See also man mktime(3). -*/ -static time_t -MakeTimeT(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t minute, int32_t second, int32_t isDst) -{ - struct tm currentTm; - currentTm.tm_year = year - 1900; - currentTm.tm_mon = month - 1; - currentTm.tm_mday = day; - currentTm.tm_hour = hour; - currentTm.tm_min = minute; - currentTm.tm_sec = second; - currentTm.tm_isdst = isDst; - return mktime(¤tTm); -} - /* Function: GetX509Thumbprint @@ -914,20 +889,14 @@ void CryptoNative_RecursiveFreeX509Stack(STACK_OF(X509) * stack) SetX509StoreVerifyTime Used by System.Security.Cryptography.X509Certificates' OpenSslX509ChainProcessor to assign the -verification time to the chain building. The input is in LOCAL time, not UTC. +verification time to the chain building. The input is an absolute instant as Unix time +(seconds since 1970-01-01 UTC), directly convertible to a time_t value. Return values: -0 if ctx is NULL, if ctx has no X509_VERIFY_PARAM, or the date inputs don't produce a valid time_t; +0 if ctx is NULL or if ctx has no X509_VERIFY_PARAM; 1 on success. */ -int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx, - int32_t year, - int32_t month, - int32_t day, - int32_t hour, - int32_t minute, - int32_t second, - int32_t isDst) +int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx, int64_t unixTime) { ERR_clear_error(); @@ -936,12 +905,7 @@ int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx, return 0; } - time_t verifyTime = MakeTimeT(year, month, day, hour, minute, second, isDst); - - if (verifyTime == (time_t)-1) - { - return 0; - } + time_t verifyTime = (time_t)unixTime; X509_VERIFY_PARAM* verifyParams = X509_STORE_get0_param(ctx); diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.h b/src/native/libs/System.Security.Cryptography.Native/openssl.h index d1ff2f8bb4aaf7..5cc1a4bf820445 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.h +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.h @@ -42,14 +42,7 @@ PALEXPORT X509* CryptoNative_GetX509StackField(STACK_OF(X509) * stack, int loc); PALEXPORT void CryptoNative_RecursiveFreeX509Stack(STACK_OF(X509) * stack); -PALEXPORT int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx, - int32_t year, - int32_t month, - int32_t day, - int32_t hour, - int32_t minute, - int32_t second, - int32_t isDst); +PALEXPORT int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx, int64_t unixTime); PALEXPORT X509* CryptoNative_ReadX509AsDerFromBio(BIO* bio); From f873d93813ac4033d986bb6151a04017c4ef7f10 Mon Sep 17 00:00:00 2001 From: Koen van Leeuwen Date: Mon, 15 Jun 2026 21:46:38 +0200 Subject: [PATCH 3/5] Apply suggestions from code review Co-authored-by: Jeremy Barton --- .../Cryptography/X509Certificates/ChainPal.OpenSsl.cs | 4 +--- .../tests/X509Certificates/ChainTests.TimeZone.Linux.cs | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs index 61bebd8d8a4b55..fdd0a23487ac73 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/ChainPal.OpenSsl.cs @@ -98,9 +98,7 @@ public static void FlushStores() timeout = s_maxUrlRetrievalTimeout; } - // Convert to an absolute instant for OpenSSL. - // (https://github.com/dotnet/runtime/issues/109039). - var verificationInstant = new DateTimeOffset(verificationTime); + DateTimeOffset verificationInstant = new DateTimeOffset(verificationTime); // Until we support the Disallowed store, ensure it's empty (which is done by the ctor) using (new X509Store(StoreName.Disallowed, StoreLocation.CurrentUser, OpenFlags.ReadOnly)) diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs index cd740e41843b06..769b92c16436bb 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs @@ -7,7 +7,6 @@ namespace System.Security.Cryptography.X509Certificates.Tests { // Chain time validity must not depend on the process time zone. - // https://github.com/dotnet/runtime/issues/109039 // OpenSSL/Linux only (Windows/macOS convert the verify time correctly). // RemoteExecutor + TZ isolates the time-zone change to a child process. [PlatformSpecific(TestPlatforms.Linux)] From bce41a44c6c860bac5dd5093e16f5fb926c2fc89 Mon Sep 17 00:00:00 2001 From: Koen van Leeuwen Date: Mon, 15 Jun 2026 22:03:00 +0200 Subject: [PATCH 4/5] Simplify tests --- .../ChainTests.TimeZone.Linux.cs | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs index 769b92c16436bb..eb4f636fcc0b0d 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.TimeZone.Linux.cs @@ -23,25 +23,16 @@ public static void ValidCert_StaysTimeValidAfterTimeZoneChange(bool asLocal) { // Validity margin (+/-2h) is narrower than the UTC+14 shift below, so the // bug (if present) moves the effective verify time outside the window. - using X509Certificate2 cert = ChainTimeZone.MakeCert(s_verify.AddHours(-2), s_verify.AddHours(2)); + using X509Certificate2 cert = MakeCert(s_verify.AddHours(-2), s_verify.AddHours(2)); bool asLocal = bool.Parse(asLocalStr); - ChainTimeZone.SetZone("UTC"); - Assert.True(ChainTimeZone.IsTimeValid(cert, s_verify, asLocal)); + SetZone("UTC"); + Assert.True(IsTimeValid(cert, s_verify, asLocal)); - ChainTimeZone.SetZone("Pacific/Kiritimati"); // UTC+14 - Assert.True(ChainTimeZone.IsTimeValid(cert, s_verify, asLocal)); + SetZone("Pacific/Kiritimati"); // UTC+14 + Assert.True(IsTimeValid(cert, s_verify, asLocal)); }, asLocal.ToString()).Dispose(); } - } - - // Companion to ChainTimeZoneTests: the opposite-sign case, an expired - // certificate must not become time-valid after a westward time-zone change. - // https://github.com/dotnet/runtime/issues/109039 - [PlatformSpecific(TestPlatforms.Linux)] - public static class ChainTimeZoneExpiredTests - { - private static readonly DateTimeOffset s_verify = new(2024, 6, 15, 12, 0, 0, TimeSpan.Zero); [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] [InlineData(false)] @@ -53,24 +44,21 @@ public static void ExpiredCert_StaysNotTimeValidAfterTimeZoneChange(bool asLocal // Expired 30 min before s_verify. NotBefore is >14h earlier so the // westward shift (~14h) lands back inside the window (re-entering // validity from the expiry side), not before NotBefore. - using X509Certificate2 cert = ChainTimeZone.MakeCert(s_verify.AddHours(-20), s_verify.AddMinutes(-30)); + using X509Certificate2 cert = MakeCert(s_verify.AddHours(-20), s_verify.AddMinutes(-30)); bool asLocal = bool.Parse(asLocalStr); - ChainTimeZone.SetZone("Pacific/Kiritimati"); // UTC+14 - Assert.False(ChainTimeZone.IsTimeValid(cert, s_verify, asLocal)); + SetZone("Pacific/Kiritimati"); // UTC+14 + Assert.False(IsTimeValid(cert, s_verify, asLocal)); - ChainTimeZone.SetZone("UTC"); // westward: "now" moves back ~14h - Assert.False(ChainTimeZone.IsTimeValid(cert, s_verify, asLocal)); + SetZone("UTC"); // westward: "now" moves back ~14h + Assert.False(IsTimeValid(cert, s_verify, asLocal)); }, asLocal.ToString()).Dispose(); } - } - internal static class ChainTimeZone - { internal static void SetZone(string tz) { Environment.SetEnvironmentVariable("TZ", tz); - TimeZoneInfo.ClearCachedData(); // required to reproduce #109039: refresh the cached local zone + TimeZoneInfo.ClearCachedData(); } internal static X509Certificate2 MakeCert(DateTimeOffset notBefore, DateTimeOffset notAfter) From 05b3d26a5f60c508c6267a3216277bd9779b4eff Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Thu, 18 Jun 2026 10:47:32 -0700 Subject: [PATCH 5/5] Update function doc comment --- src/native/libs/System.Security.Cryptography.Native/openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index 4e366d90d5a1e4..d31ebf441529e9 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -893,7 +893,7 @@ verification time to the chain building. The input is an absolute instant as Uni (seconds since 1970-01-01 UTC), directly convertible to a time_t value. Return values: -0 if ctx is NULL or if ctx has no X509_VERIFY_PARAM; +0 if ctx is NULL, if ctx has no X509_VERIFY_PARAM, or if the time is out of bounds on a 32-bit time environment. 1 on success. */ int32_t CryptoNative_X509StoreSetVerifyTime(X509_STORE* ctx, int64_t unixTime)