// Copyright (C) 2024 Vaughn Nugent // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . using System; using System.Runtime.InteropServices; using VNLib.Utils; using VNLib.Utils.Native; using VNLib.Utils.Extensions; namespace VNLib.Utils.Cryptography.Noscrypt { /// /// A wrapper class for an unmanaged random source that conforms to the interface /// public class UnmanagedRandomSource : VnDisposeable, IRandomSource { /// /// The explicit name of the unmanaged random function to get random bytes /// public const string RngFunctionName = "GetRandomBytes"; unsafe delegate void UnmanagedRandomSourceDelegate(byte* buffer, int size); private readonly bool OwnsHandle; private readonly SafeLibraryHandle _library; private readonly UnmanagedRandomSourceDelegate _getRandomBytes; /// /// Loads the unmanaged random source from the given library /// and attempts to get the random bytes method /// /// /// /// The wrapped library that conforms to the public static UnmanagedRandomSource LoadLibrary(string path, DllImportSearchPath search) { //Try to load the library SafeLibraryHandle lib = SafeLibraryHandle.LoadLibrary(path, search); try { return new UnmanagedRandomSource(lib, true); } catch { //release lib lib.Dispose(); throw; } } /// /// Creates the unmanaged random source from the given library /// /// The library handle to wrap /// /// public UnmanagedRandomSource(SafeLibraryHandle lib, bool ownsHandle) { lib.ThrowIfClosed(); _library = lib; //get the method delegate _getRandomBytes = lib.DangerousGetFunction(RngFunctionName); OwnsHandle = ownsHandle; } /// public unsafe void GetRandomBytes(Span buffer) { _library.ThrowIfClosed(); //Fix buffer and call unmanaged method fixed (byte* ptr = &MemoryMarshal.GetReference(buffer)) { _getRandomBytes(ptr, buffer.Length); } } /// protected override void Free() { if (OwnsHandle) { _library.Dispose(); } } } }