public Entry(string hashAlgorithmId, BCryptOpenAlgorithmProviderFlags flags, SafeBCryptAlgorithmHandle handle) : this() { HashAlgorithmId = hashAlgorithmId; Flags = flags; Handle = handle; }
/// <summary> /// Return a SafeBCryptAlgorithmHandle of the desired algorithm and flags. This is a shared handle so do not dispose it! /// </summary> public static SafeBCryptAlgorithmHandle GetCachedBCryptAlgorithmHandle(string hashAlgorithmId, BCryptOpenAlgorithmProviderFlags flags) { // There aren't that many hash algorithms around so rather than use a LowLevelDictionary and guard it with a lock, // we'll use a simple list. To avoid locking, we'll recreate the entire list each time an entry is added and replace it atomically. // // This does mean that on occasion, racing threads may create two handles of the same type, but this is ok. // Latch the _cache value into a local so we aren't disrupted by concurrent changes to it. Entry[] cache = _cache; foreach (Entry entry in cache) { if (entry.HashAlgorithmId == hashAlgorithmId && entry.Flags == flags) return entry.Handle; } SafeBCryptAlgorithmHandle safeBCryptAlgorithmHandle; NTSTATUS ntStatus = Interop.BCrypt.BCryptOpenAlgorithmProvider(out safeBCryptAlgorithmHandle, hashAlgorithmId, null, flags); if (ntStatus != NTSTATUS.STATUS_SUCCESS) throw Interop.BCrypt.CreateCryptographicException(ntStatus); Entry[] newCache = new Entry[cache.Length + 1]; Entry newEntry = new Entry(hashAlgorithmId, flags, safeBCryptAlgorithmHandle); Array.Copy(cache, 0, newCache, 0, cache.Length); newCache[newCache.Length - 1] = newEntry; // Atomically overwrite the cache with our new cache. It's possible some other thread raced to add a new entry with us - if so, one of the new entries // will be lost and the next guy that requests it will have to allocate it again. That's considered acceptable collateral damage. _cache = newCache; return newEntry.Handle; }
/// <summary> /// Loads and initializes a CNG provider. /// </summary> /// <param name="pszAlgId"> /// A pointer to a null-terminated Unicode string that identifies the requested /// cryptographic algorithm. This can be one of the standard /// CNG Algorithm Identifiers defined in <see cref="AlgorithmIdentifiers"/> /// or the identifier for another registered algorithm. /// </param> /// <param name="pszImplementation"> /// <para> /// A pointer to a null-terminated Unicode string that identifies the specific provider /// to load. This is the registered alias of the cryptographic primitive provider. /// This parameter is optional and can be NULL if it is not needed. If this parameter /// is NULL, the default provider for the specified algorithm will be loaded. /// </para> /// <para> /// Note If the <paramref name="pszImplementation"/> parameter value is NULL, CNG attempts to open each /// registered provider, in order of priority, for the algorithm specified by the /// <paramref name="pszAlgId"/> parameter and returns the handle of the first provider that is successfully /// opened.For the lifetime of the handle, any BCrypt*** cryptographic APIs will use the /// provider that was successfully opened. /// </para> /// </param> /// <param name="dwFlags">Options for the function.</param> /// <returns> /// A pointer to a BCRYPT_ALG_HANDLE variable that receives the CNG provider handle. /// When you have finished using this handle, release it by passing it to the /// BCryptCloseAlgorithmProvider function. /// </returns> public static SafeAlgorithmHandle BCryptOpenAlgorithmProvider( string pszAlgId, string pszImplementation = null, BCryptOpenAlgorithmProviderFlags dwFlags = BCryptOpenAlgorithmProviderFlags.None) { SafeAlgorithmHandle handle; BCryptOpenAlgorithmProvider( out handle, pszAlgId, pszImplementation, dwFlags).ThrowOnError(); return(handle); }
internal static extern NTSTATUS BCryptOpenAlgorithmProvider(out SafeBCryptAlgorithmHandle phAlgorithm, string pszAlgId, string pszImplementation, BCryptOpenAlgorithmProviderFlags dwFlags);
/// <summary> /// Return a SafeBCryptAlgorithmHandle of the desired algorithm and flags. This is a shared handle so do not dispose it! /// </summary> public static SafeBCryptAlgorithmHandle GetCachedBCryptAlgorithmHandle(string hashAlgorithmId, BCryptOpenAlgorithmProviderFlags flags, out int hashSizeInBytes) { // There aren't that many hash algorithms around so rather than use a LowLevelDictionary and guard it with a lock, // we'll use a simple list. To avoid locking, we'll recreate the entire list each time an entry is added and replace it atomically. // // This does mean that on occasion, racing threads may create two handles of the same type, but this is ok. // Latch the _cache value into a local so we aren't disrupted by concurrent changes to it. Entry[] cache = _cache; foreach (Entry entry in cache) { if (entry.HashAlgorithmId == hashAlgorithmId && entry.Flags == flags) { hashSizeInBytes = entry.HashSizeInBytes; return(entry.Handle); } } SafeBCryptAlgorithmHandle safeBCryptAlgorithmHandle; NTSTATUS ntStatus = Interop.BCrypt.BCryptOpenAlgorithmProvider(out safeBCryptAlgorithmHandle, hashAlgorithmId, null, flags); if (ntStatus != NTSTATUS.STATUS_SUCCESS) { throw Interop.BCrypt.CreateCryptographicException(ntStatus); } Array.Resize(ref cache, cache.Length + 1); Entry newEntry = new Entry(hashAlgorithmId, flags, safeBCryptAlgorithmHandle); cache[^ 1] = new Entry(hashAlgorithmId, flags, safeBCryptAlgorithmHandle);
internal static extern int BCryptOpenAlgorithmProvider(out SafeBCryptAlgorithmHandle algorithmHandle, string algIdString, string implementationString, BCryptOpenAlgorithmProviderFlags flags);
public static extern NTStatus BCryptOpenAlgorithmProvider( out SafeAlgorithmHandle phAlgorithm, string pszAlgId, string pszImplementation, BCryptOpenAlgorithmProviderFlags dwFlags);
/// <summary> /// Return a SafeBCryptAlgorithmHandle of the desired algorithm and flags. This is a shared handle so do not dispose it! /// </summary> public static SafeBCryptAlgorithmHandle GetCachedBCryptAlgorithmHandle(string hashAlgorithmId, BCryptOpenAlgorithmProviderFlags flags) { // There aren't that many hash algorithms around so rather than use a LowLevelDictionary and guard it with a lock, // we'll use a simple list. To avoid locking, we'll recreate the entire list each time an entry is added and replace it atomically. // // This does mean that on occasion, racing threads may create two handles of the same type, but this is ok. // Latch the _cache value into a local so we aren't disrupted by concurrent changes to it. Entry[] cache = _cache; foreach (Entry entry in cache) { if (entry.HashAlgorithmId == hashAlgorithmId && entry.Flags == flags) { return(entry.Handle); } } SafeBCryptAlgorithmHandle safeBCryptAlgorithmHandle; NTSTATUS ntStatus = Interop.BCrypt.BCryptOpenAlgorithmProvider(out safeBCryptAlgorithmHandle, hashAlgorithmId, null, flags); if (ntStatus != NTSTATUS.STATUS_SUCCESS) { throw Interop.BCrypt.CreateCryptographicException(ntStatus); } Entry[] newCache = new Entry[cache.Length + 1]; Entry newEntry = new Entry(hashAlgorithmId, flags, safeBCryptAlgorithmHandle); Array.Copy(cache, 0, newCache, 0, cache.Length); newCache[newCache.Length - 1] = newEntry; // Atomically overwrite the cache with our new cache. It's possible some other thread raced to add a new entry with us - if so, one of the new entries // will be lost and the next guy that requests it will have to allocate it again. That's considered acceptable collateral damage. _cache = newCache; return(newEntry.Handle); }
public static extern NtStatus BCryptOpenAlgorithmProvider( out IntPtr phAlgorithm, string pszAlgId, string pszImplementation = null, BCryptOpenAlgorithmProviderFlags dwFlags = BCryptOpenAlgorithmProviderFlags.None );
/// <summary> /// Returns a SafeBCryptAlgorithmHandle of the desired algorithm and flags. This is a shared handle so do not dispose it! /// </summary> public static unsafe SafeBCryptAlgorithmHandle GetCachedBCryptAlgorithmHandle(string hashAlgorithmId, BCryptOpenAlgorithmProviderFlags flags, out int hashSizeInBytes) { var key = (hashAlgorithmId, flags); while (true) { if (s_handles.TryGetValue(key, out (SafeBCryptAlgorithmHandle Handle, int HashSizeInBytes)result)) { hashSizeInBytes = result.HashSizeInBytes; return(result.Handle); } NTSTATUS ntStatus = Interop.BCrypt.BCryptOpenAlgorithmProvider(out SafeBCryptAlgorithmHandle handle, key.hashAlgorithmId, null, key.flags); if (ntStatus != NTSTATUS.STATUS_SUCCESS) { Exception e = Interop.BCrypt.CreateCryptographicException(ntStatus); handle.Dispose(); throw e; } int hashSize; ntStatus = Interop.BCrypt.BCryptGetProperty( handle, Interop.BCrypt.BCryptPropertyStrings.BCRYPT_HASH_LENGTH, &hashSize, sizeof(int), out int cbHashSize, 0); if (ntStatus != NTSTATUS.STATUS_SUCCESS) { Exception e = Interop.BCrypt.CreateCryptographicException(ntStatus); handle.Dispose(); throw e; } Debug.Assert(cbHashSize == sizeof(int)); Debug.Assert(hashSize > 0); if (!s_handles.TryAdd(key, (handle, hashSize))) { handle.Dispose(); } } }
internal static extern int BCryptOpenAlgorithmProvider(out IntPtr phAlgorithm, string pszAlgId, string pszImplementation, BCryptOpenAlgorithmProviderFlags dwFlags);