authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-05 12:16:54-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-05 12:16:54-08:00
logd3d6761e4367df3fc72f33681c36dc67471cf63f
tree9ed98c325bc6596e0f1653266768794982f183cc
parent52141fe85f1b7719cecb868520f40431fcfff2a1

std: depend on NtDll rather than advapi32.dll for entropy


4 files changed, 58 insertions(+), 31 deletions(-)

lib/std/Io/Threaded.zig+1-1
...@@ -13674,7 +13674,7 @@ fn getNulHandle(t: *Threaded) !windows.HANDLE {...@@ -13674,7 +13674,7 @@ fn getNulHandle(t: *Threaded) !windows.HANDLE {
13674 const device_path = [_]u16{ '\\', 'D', 'e', 'v', 'i', 'c', 'e', '\\', 'N', 'u', 'l', 'l' };13674 const device_path = [_]u16{ '\\', 'D', 'e', 'v', 'i', 'c', 'e', '\\', 'N', 'u', 'l', 'l' };
13675 var nt_name: windows.UNICODE_STRING = .{13675 var nt_name: windows.UNICODE_STRING = .{
13676 .Length = device_path.len * 2,13676 .Length = device_path.len * 2,
13677 .MaximumLength = device_path.len * 2,13677 .MaximumLength = 0,
13678 .Buffer = @constCast(&device_path),13678 .Buffer = @constCast(&device_path),
13679 };13679 };
13680 const attr: windows.OBJECT_ATTRIBUTES = .{13680 const attr: windows.OBJECT_ATTRIBUTES = .{
lib/std/os/windows.zig+56-24
...@@ -1080,6 +1080,9 @@ pub const CTL_CODE = packed struct(ULONG) {...@@ -1080,6 +1080,9 @@ pub const CTL_CODE = packed struct(ULONG) {
1080};1080};
10811081
1082pub const IOCTL = struct {1082pub const IOCTL = struct {
1083 pub const KSEC = struct {
1084 pub const GEN_RANDOM: CTL_CODE = .{ .DeviceType = .KSEC, .Function = 2, .Method = .BUFFERED, .Access = .ANY };
1085 };
1083 pub const MOUNTMGR = struct {1086 pub const MOUNTMGR = struct {
1084 pub const QUERY_POINTS: CTL_CODE = .{ .DeviceType = .MOUNTMGRCONTROLTYPE, .Function = 2, .Method = .BUFFERED, .Access = .ANY };1087 pub const QUERY_POINTS: CTL_CODE = .{ .DeviceType = .MOUNTMGRCONTROLTYPE, .Function = 2, .Method = .BUFFERED, .Access = .ANY };
1085 pub const QUERY_DOS_VOLUME_PATH: CTL_CODE = .{ .DeviceType = .MOUNTMGRCONTROLTYPE, .Function = 12, .Method = .BUFFERED, .Access = .ANY };1088 pub const QUERY_DOS_VOLUME_PATH: CTL_CODE = .{ .DeviceType = .MOUNTMGRCONTROLTYPE, .Function = 12, .Method = .BUFFERED, .Access = .ANY };
...@@ -2644,30 +2647,59 @@ pub fn SetHandleInformation(h: HANDLE, mask: DWORD, flags: DWORD) SetHandleInfor...@@ -2644,30 +2647,59 @@ pub fn SetHandleInformation(h: HANDLE, mask: DWORD, flags: DWORD) SetHandleInfor
2644 }2647 }
2645}2648}
26462649
2647pub const RtlGenRandomError = error{2650/// An alternate implementation of ProcessPrng from bcryptprimitives.dll
2648 /// `RtlGenRandom` has been known to fail in situations where the system is under heavy load.2651/// This one has the following differences:
2649 /// Unfortunately, it does not call `SetLastError`, so it is not possible to get more specific2652/// * does not heap allocate `buffer`
2650 /// error information; it could actually be due to an out-of-memory condition, for example.2653/// * does not introduce a dependency on bcryptprimitives.dll, which apparently
2651 SystemResources,2654/// runs a test suite every time it is loaded
2652};2655/// * reads buffer.len bytes from "\\Device\\CNG" rather than seeding a per-CPU
26532656/// AES csprng with 48 bytes.
2654/// Call RtlGenRandom() instead of CryptGetRandom() on Windows2657pub fn ProcessPrng(buffer: []u8) error{Unexpected}!void {
2655/// https://github.com/rust-lang-nursery/rand/issues/1112658 const device_path = [_]u16{ '\\', 'D', 'e', 'v', 'i', 'c', 'e', '\\', 'C', 'N', 'G' };
2656/// https://bugzilla.mozilla.org/show_bug.cgi?id=5042702659 var nt_name: UNICODE_STRING = .{
2657pub fn RtlGenRandom(output: []u8) RtlGenRandomError!void {2660 .Length = device_path.len * 2,
2658 var total_read: usize = 0;2661 .MaximumLength = 0,
2659 var buff: []u8 = output[0..];2662 .Buffer = @constCast(&device_path),
2660 const max_read_size: ULONG = maxInt(ULONG);2663 };
26612664 var cng_device: HANDLE = undefined;
2662 while (total_read < output.len) {2665 var io_status_block: IO_STATUS_BLOCK = undefined;
2663 const to_read: ULONG = @min(buff.len, max_read_size);2666 switch (ntdll.NtOpenFile(
26642667 &cng_device,
2665 if (advapi32.RtlGenRandom(buff.ptr, to_read) == 0) {2668 .{
2666 return error.SystemResources;2669 .STANDARD = .{ .SYNCHRONIZE = true },
2667 }2670 .SPECIFIC = .{ .FILE = .{ .READ_DATA = true } },
26682671 },
2669 total_read += to_read;2672 &.{
2670 buff = buff[to_read..];2673 .Length = @sizeOf(OBJECT_ATTRIBUTES),
2674 .RootDirectory = null,
2675 .ObjectName = &nt_name,
2676 .Attributes = .{},
2677 .SecurityDescriptor = null,
2678 .SecurityQualityOfService = null,
2679 },
2680 &io_status_block,
2681 .VALID_FLAGS,
2682 .{ .IO = .SYNCHRONOUS_NONALERT },
2683 )) {
2684 .SUCCESS => {},
2685 .OBJECT_NAME_NOT_FOUND => return error.Unexpected, // Observed on wine 10.0
2686 else => |status| return unexpectedStatus(status),
2687 }
2688 defer _ = ntdll.NtClose(cng_device);
2689 switch (ntdll.NtDeviceIoControlFile(
2690 cng_device,
2691 null,
2692 null,
2693 null,
2694 &io_status_block,
2695 IOCTL.KSEC.GEN_RANDOM,
2696 null,
2697 0,
2698 buffer.ptr,
2699 @intCast(buffer.len),
2700 )) {
2701 .SUCCESS => {},
2702 else => |status| return unexpectedStatus(status),
2671 }2703 }
2672}2704}
26732705
lib/std/os/windows/advapi32.zig-5
...@@ -28,11 +28,6 @@ pub extern "advapi32" fn RegQueryValueExW(...@@ -28,11 +28,6 @@ pub extern "advapi32" fn RegQueryValueExW(
2828
29pub extern "advapi32" fn RegCloseKey(hKey: HKEY) callconv(.winapi) LSTATUS;29pub extern "advapi32" fn RegCloseKey(hKey: HKEY) callconv(.winapi) LSTATUS;
3030
31// RtlGenRandom is known as SystemFunction036 under advapi32
32// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */
33pub extern "advapi32" fn SystemFunction036(output: [*]u8, length: ULONG) callconv(.winapi) BOOL;
34pub const RtlGenRandom = SystemFunction036;
35
36pub const RRF = struct {31pub const RRF = struct {
37 pub const RT_ANY: DWORD = 0x0000ffff;32 pub const RT_ANY: DWORD = 0x0000ffff;
3833
lib/std/posix.zig+1-1
...@@ -370,7 +370,7 @@ pub const GetRandomError = OpenError;...@@ -370,7 +370,7 @@ pub const GetRandomError = OpenError;
370/// library implementation.370/// library implementation.
371pub fn getrandom(buffer: []u8) GetRandomError!void {371pub fn getrandom(buffer: []u8) GetRandomError!void {
372 if (native_os == .windows) {372 if (native_os == .windows) {
373 return windows.RtlGenRandom(buffer);373 return windows.ProcessPrng(buffer);
374 }374 }
375 if (builtin.link_libc and @TypeOf(system.arc4random_buf) != void) {375 if (builtin.link_libc and @TypeOf(system.arc4random_buf) != void) {
376 system.arc4random_buf(buffer.ptr, buffer.len);376 system.arc4random_buf(buffer.ptr, buffer.len);