// Copyright (C) 2023 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 NVault.Crypto.Secp256k1 { /// /// A wrapper class for an unmanaged random source that conforms to the interface /// public class UnmanagedRandomSource : VnDisposeable, IRandomSource { public const string METHOD_NAME = "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.DangerousGetMethod(METHOD_NAME); 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(); } } } }