using Org.BouncyCastle.Crypto.Prng; using Org.BouncyCastle.Security; namespace XFESystem.Tls; /// The platform must reject unavailable entropy and untrustworthy UTC; no fallback is allowed. public interface ITlsSecurityContext { DateTime UtcNow { get; } void FillRandom(Span destination); } internal sealed class PlatformRandomGenerator(ITlsSecurityContext platform) : IRandomGenerator { // Bouncy Castle may add supplemental public material. It must never replace // the independently seeded, platform-owned CSPRNG with this material. public void AddSeedMaterial(byte[] seed) { } public void AddSeedMaterial(ReadOnlySpan seed) { } public void AddSeedMaterial(long seed) { } public void NextBytes(byte[] bytes) => platform.FillRandom(bytes); public void NextBytes(byte[] bytes, int start, int len) => platform.FillRandom(bytes.AsSpan(start, len)); public void NextBytes(Span bytes) => platform.FillRandom(bytes); } internal static class TlsSecurity { public static DateTime ReadUtc(ITlsSecurityContext platform) { DateTime now = platform.UtcNow; ValidateUtc(now); return now; } internal static void ValidateUtc(DateTime now) { if (now.Kind != DateTimeKind.Utc || now < new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc)) throw new InvalidOperationException("HTTPS requires a reliable UTC clock."); } public static SecureRandom CreateRandom(ITlsSecurityContext platform) { // Probe before the ClientHello. This is an availability check, not an // entropy estimate; the platform performs the actual source checks. Span probe = stackalloc byte[32]; try { platform.FillRandom(probe); } finally { probe.Clear(); } return new SecureRandom(new PlatformRandomGenerator(platform)); } }