BCrypt: Add
Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
ba13a57897
commit
289aab2354
309
include/WinStd/BCrypt.h
Normal file
309
include/WinStd/BCrypt.h
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
/*
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
Copyright © 1991-2025 Amebis
|
||||||
|
Copyright © 2016 GÉANT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// \defgroup WinStdBCryptAPI Cryptography API
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Win.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <bcrypt.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/// \addtogroup WinStdBCryptAPI
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Implements default constructors and operators to prevent their auto-generation by compiler.
|
||||||
|
///
|
||||||
|
#define WINSTD_BCRYPT_HWO_IMPL(C, T) \
|
||||||
|
public: \
|
||||||
|
C ( ) noexcept {} \
|
||||||
|
C (_In_ const C &h) { if (h.m_h != invalid) duplicate_internal(h); } \
|
||||||
|
C (_Inout_ C &&h) noexcept : bcrypt_handle_with_object<T>(std::move(h)) {} \
|
||||||
|
C& operator=(_In_ const C &h) { bcrypt_handle_with_object<T>::operator=( h ); return *this; } \
|
||||||
|
C& operator=(_Inout_ C &&h) noexcept { bcrypt_handle_with_object<T>::operator=(std::move(h)); return *this; } \
|
||||||
|
private:
|
||||||
|
|
||||||
|
template<class _Ty, class _Ax>
|
||||||
|
static _Must_inspect_result_ NTSTATUS BCryptSignHash(_In_ BCRYPT_KEY_HANDLE hKey, _In_opt_ VOID *pPaddingInfo, _In_reads_bytes_(cbInput) PUCHAR pbInput, _In_ ULONG cbInput, _Out_ std::vector<_Ty, _Ax> &aOutput, _In_ ULONG dwFlags)
|
||||||
|
{
|
||||||
|
ULONG cbSignature = 0;
|
||||||
|
NTSTATUS status = BCryptSignHash(hKey, pPaddingInfo, pbInput, cbInput, NULL, 0, &cbSignature, dwFlags);
|
||||||
|
if (!status) {
|
||||||
|
aOutput.resize((cbSignature + sizeof(_Ty) - 1) / sizeof(_Ty));
|
||||||
|
status = BCryptSignHash(hKey, NULL, pbInput, cbInput, aOutput.data(), cbSignature, &cbSignature, dwFlags);
|
||||||
|
if (!status)
|
||||||
|
aOutput.resize((cbSignature + sizeof(_Ty) - 1) / sizeof(_Ty));
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class _Ty, class _Ax>
|
||||||
|
static _Must_inspect_result_ NTSTATUS BCryptExportKey(_In_ BCRYPT_KEY_HANDLE hKey, _In_opt_ BCRYPT_KEY_HANDLE hExportKey, _In_z_ LPCWSTR pszBlobType, _Out_ std::vector<_Ty, _Ax> &aOutput, _In_ ULONG dwFlags)
|
||||||
|
{
|
||||||
|
DWORD cbBlob = 0;
|
||||||
|
NTSTATUS status = BCryptExportKey(hKey, hExportKey, pszBlobType, NULL, 0, &cbBlob, dwFlags);
|
||||||
|
if (!status) {
|
||||||
|
aOutput.resize((cbBlob + sizeof(_Ty) - 1) / sizeof(_Ty));
|
||||||
|
status = BCryptExportKey(hKey, hExportKey, pszBlobType, aOutput.data(), cbBlob, &cbBlob, dwFlags);
|
||||||
|
if (!status)
|
||||||
|
aOutput.resize((cbBlob + sizeof(_Ty) - 1) / sizeof(_Ty));
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
namespace winstd
|
||||||
|
{
|
||||||
|
/// \addtogroup WinStdBCryptAPI
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// BCRYPT_ALG_HANDLE wrapper class
|
||||||
|
///
|
||||||
|
/// \sa [BCryptOpenAlgorithmProvider function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptopenalgorithmprovider)
|
||||||
|
///
|
||||||
|
class bcrypt_algorithm_provider : public handle<BCRYPT_ALG_HANDLE, NULL>
|
||||||
|
{
|
||||||
|
WINSTD_HANDLE_IMPL(bcrypt_algorithm_provider, BCRYPT_ALG_HANDLE, NULL)
|
||||||
|
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
/// Releases the algorithm provider.
|
||||||
|
///
|
||||||
|
/// \sa [BCryptCloseAlgorithmProvider function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptclosealgorithmprovider)
|
||||||
|
///
|
||||||
|
virtual ~bcrypt_algorithm_provider()
|
||||||
|
{
|
||||||
|
if (m_h != invalid)
|
||||||
|
free_internal();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///
|
||||||
|
/// Releases the algorithm provider.
|
||||||
|
///
|
||||||
|
/// \sa [BCryptCloseAlgorithmProvider function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptclosealgorithmprovider)
|
||||||
|
///
|
||||||
|
void free_internal() noexcept override
|
||||||
|
{
|
||||||
|
BCryptCloseAlgorithmProvider(m_h, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class bcrypt_handle_with_object : public handle<T, NULL>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bcrypt_handle_with_object<T>() noexcept {}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Move constructor
|
||||||
|
///
|
||||||
|
/// \param[inout] h A rvalue reference of another object
|
||||||
|
///
|
||||||
|
bcrypt_handle_with_object<T>(_Inout_ bcrypt_handle_with_object<T>&& h) noexcept :
|
||||||
|
handle<T, NULL>(std::move(h)),
|
||||||
|
m_hash_object(std::move(h.m_hash_object))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Duplicates the object.
|
||||||
|
///
|
||||||
|
/// \param[in] h Object
|
||||||
|
///
|
||||||
|
bcrypt_handle_with_object<T>& operator=(_In_ const bcrypt_handle_with_object<T>& h)
|
||||||
|
{
|
||||||
|
if (this != std::addressof(h)) {
|
||||||
|
if (m_h != invalid)
|
||||||
|
free_internal();
|
||||||
|
if (h)
|
||||||
|
duplicate_internal(h);
|
||||||
|
else
|
||||||
|
m_h = invalid;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Move assignment
|
||||||
|
///
|
||||||
|
/// \param[inout] h A rvalue reference of another object
|
||||||
|
///
|
||||||
|
bcrypt_handle_with_object<T>& operator=(_Inout_ bcrypt_handle_with_object<T>&& h) noexcept
|
||||||
|
{
|
||||||
|
if (this != std::addressof(h)) {
|
||||||
|
handle<T, NULL>::operator=(std::move(h));
|
||||||
|
m_hash_object = std::move(h.m_hash_object);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///
|
||||||
|
/// Abstract member function that must be implemented by child classes to do the actual object duplication.
|
||||||
|
///
|
||||||
|
/// \param[inout] h A reference of another object
|
||||||
|
///
|
||||||
|
virtual void duplicate_internal(_In_ const bcrypt_handle_with_object<T>& h) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<UCHAR> m_hash_object;
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// BCRYPT_HASH_HANDLE wrapper class
|
||||||
|
///
|
||||||
|
class bcrypt_hash : public bcrypt_handle_with_object<BCRYPT_HASH_HANDLE>
|
||||||
|
{
|
||||||
|
WINSTD_BCRYPT_HWO_IMPL(bcrypt_hash, BCRYPT_HASH_HANDLE)
|
||||||
|
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
/// Creates a hash.
|
||||||
|
///
|
||||||
|
/// \sa [BCryptCreateHash function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379908.aspx)
|
||||||
|
///
|
||||||
|
bcrypt_hash(_In_ BCRYPT_ALG_HANDLE hAlgorithm, _In_reads_bytes_opt_(cbSecret) PUCHAR pbSecret, _In_ ULONG cbSecret, _In_ ULONG dwFlags)
|
||||||
|
{
|
||||||
|
ULONG hashObjectSize, bytesRead;
|
||||||
|
NTSTATUS status = BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, reinterpret_cast<PUCHAR>(&hashObjectSize), sizeof(hashObjectSize), &bytesRead, 0);
|
||||||
|
if (status || bytesRead != sizeof(hashObjectSize))
|
||||||
|
throw ntstatus_error(status, "Failed to get hash object size");
|
||||||
|
m_hash_object.resize(hashObjectSize);
|
||||||
|
status = BCryptCreateHash(hAlgorithm, &m_h, m_hash_object.data(), static_cast<DWORD>(m_hash_object.size()), pbSecret, cbSecret, dwFlags);
|
||||||
|
if (status)
|
||||||
|
throw ntstatus_error(status, "Failed to create hash");
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Destroys the hash.
|
||||||
|
///
|
||||||
|
/// \sa [BCryptDestroyHash function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptdestroyhash)
|
||||||
|
///
|
||||||
|
virtual ~bcrypt_hash()
|
||||||
|
{
|
||||||
|
if (m_h != invalid)
|
||||||
|
free_internal();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///
|
||||||
|
/// Destroys the hash.
|
||||||
|
///
|
||||||
|
/// \sa [BCryptDestroyHash function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptdestroyhash)
|
||||||
|
///
|
||||||
|
void free_internal() noexcept override
|
||||||
|
{
|
||||||
|
BCryptDestroyHash(m_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Duplicates an existing hash or Message Authentication Code (MAC) object.
|
||||||
|
///
|
||||||
|
/// \sa [BCryptDuplicateHash function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptduplicatehash)
|
||||||
|
///
|
||||||
|
void duplicate_internal(_In_ const bcrypt_handle_with_object<BCRYPT_HASH_HANDLE>& h) override
|
||||||
|
{
|
||||||
|
auto h2 = reinterpret_cast<const bcrypt_hash*>(&h);
|
||||||
|
m_hash_object.resize(h2->m_hash_object.size());
|
||||||
|
assert(m_hash_object.size() < ULONG_MAX);
|
||||||
|
NTSTATUS status = BCryptDuplicateHash(h2->m_h, &m_h, m_hash_object.data(), static_cast<ULONG>(m_hash_object.size()), 0);
|
||||||
|
if (status)
|
||||||
|
throw ntstatus_error(status, "Failed to duplicate hash");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// BCRYPT_KEY_HANDLE wrapper class for symetrical keys
|
||||||
|
///
|
||||||
|
class bcrypt_key : public bcrypt_handle_with_object<BCRYPT_KEY_HANDLE>
|
||||||
|
{
|
||||||
|
WINSTD_BCRYPT_HWO_IMPL(bcrypt_key, BCRYPT_KEY_HANDLE)
|
||||||
|
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
/// Destroys the key.
|
||||||
|
///
|
||||||
|
/// \sa [BCryptDestroyKey function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptdestroykey)
|
||||||
|
///
|
||||||
|
virtual ~bcrypt_key()
|
||||||
|
{
|
||||||
|
if (m_h != invalid)
|
||||||
|
free_internal();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///
|
||||||
|
/// Destroys the key.
|
||||||
|
///
|
||||||
|
/// \sa [BCryptDestroyKey function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptdestroykey)
|
||||||
|
///
|
||||||
|
void free_internal() noexcept override
|
||||||
|
{
|
||||||
|
BCryptDestroyKey(m_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Creates a duplicate of a symmetric key.
|
||||||
|
///
|
||||||
|
/// \sa [BCryptDuplicateKey function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptduplicatekey)
|
||||||
|
///
|
||||||
|
void duplicate_internal(_In_ const bcrypt_handle_with_object<BCRYPT_KEY_HANDLE>& h) override
|
||||||
|
{
|
||||||
|
auto h2 = reinterpret_cast<const bcrypt_key*>(&h);
|
||||||
|
m_key_object.resize(h2->m_key_object.size());
|
||||||
|
assert(m_key_object.size() < ULONG_MAX);
|
||||||
|
NTSTATUS status = BCryptDuplicateKey(h2->m_h, &m_h, m_key_object.data(), static_cast<ULONG>(m_key_object.size()), 0);
|
||||||
|
if (status)
|
||||||
|
throw ntstatus_error(status, "Failed to duplicate key");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<UCHAR> m_key_object;
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// BCRYPT_KEY_HANDLE wrapper class for keypairs
|
||||||
|
///
|
||||||
|
/// \sa [BCryptImportKeyPair function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptimportkeypair)
|
||||||
|
/// \sa [BCryptGenerateKeyPair function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgeneratekeypair)
|
||||||
|
///
|
||||||
|
class bcrypt_keypair : public handle<BCRYPT_KEY_HANDLE, NULL>
|
||||||
|
{
|
||||||
|
WINSTD_HANDLE_IMPL(bcrypt_keypair, BCRYPT_KEY_HANDLE, NULL)
|
||||||
|
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
/// Releases the algorithm provider.
|
||||||
|
///
|
||||||
|
/// \sa [BCryptCloseAlgorithmProvider function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptclosealgorithmprovider)
|
||||||
|
///
|
||||||
|
virtual ~bcrypt_keypair()
|
||||||
|
{
|
||||||
|
if (m_h != invalid)
|
||||||
|
free_internal();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///
|
||||||
|
/// Releases the algorithm provider.
|
||||||
|
///
|
||||||
|
/// \sa [BCryptCloseAlgorithmProvider function](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptclosealgorithmprovider)
|
||||||
|
///
|
||||||
|
void free_internal() noexcept override
|
||||||
|
{
|
||||||
|
BCryptCloseAlgorithmProvider(m_h, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user