aes_gcm_encrypt.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. #include "aes_gcm_encrypt.h"
  2. #include <Windows.h>
  3. #include <bcrypt.h>
  4. #include <limits>
  5. namespace sunrise::middleware::crypto::aes_gcm {
  6. /** Encrypts one buffer and returns its tag apart from the ciphertext. */
  7. bool encrypt(std::span<const std::byte, kKeySize> key,
  8. std::span<const std::byte, kNonceSize> nonce,
  9. std::span<const std::byte> plaintext,
  10. std::span<std::byte> output,
  11. std::span<std::byte, kTagSize> tag) noexcept {
  12. if (plaintext.size() > (std::numeric_limits<ULONG>::max)()
  13. || output.size() < plaintext.size()) {
  14. return false;
  15. }
  16. BCRYPT_ALG_HANDLE algorithm = nullptr;
  17. if (BCryptOpenAlgorithmProvider(&algorithm, BCRYPT_AES_ALGORITHM, nullptr, 0) < 0) {
  18. return false;
  19. }
  20. BCRYPT_KEY_HANDLE symmetricKey = nullptr;
  21. bool sealed = false;
  22. if (BCryptSetProperty(algorithm,
  23. BCRYPT_CHAINING_MODE,
  24. reinterpret_cast<PUCHAR>(const_cast<wchar_t*>(BCRYPT_CHAIN_MODE_GCM)),
  25. sizeof(BCRYPT_CHAIN_MODE_GCM),
  26. 0)
  27. >= 0
  28. && BCryptGenerateSymmetricKey(algorithm,
  29. &symmetricKey,
  30. nullptr,
  31. 0,
  32. reinterpret_cast<PUCHAR>(const_cast<std::byte*>(key.data())),
  33. static_cast<ULONG>(key.size()),
  34. 0)
  35. >= 0) {
  36. BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authentication;
  37. BCRYPT_INIT_AUTH_MODE_INFO(authentication);
  38. authentication.pbNonce = reinterpret_cast<PUCHAR>(const_cast<std::byte*>(nonce.data()));
  39. authentication.cbNonce = static_cast<ULONG>(nonce.size());
  40. authentication.pbTag = reinterpret_cast<PUCHAR>(tag.data());
  41. authentication.cbTag = static_cast<ULONG>(tag.size());
  42. ULONG produced = 0;
  43. sealed = BCryptEncrypt(symmetricKey,
  44. reinterpret_cast<PUCHAR>(const_cast<std::byte*>(plaintext.data())),
  45. static_cast<ULONG>(plaintext.size()),
  46. &authentication,
  47. nullptr,
  48. 0,
  49. reinterpret_cast<PUCHAR>(output.data()),
  50. static_cast<ULONG>(output.size()),
  51. &produced,
  52. 0)
  53. >= 0
  54. && produced == plaintext.size();
  55. BCryptDestroyKey(symmetricKey);
  56. }
  57. BCryptCloseAlgorithmProvider(algorithm, 0);
  58. return sealed;
  59. }
  60. } // namespace sunrise::middleware::crypto::aes_gcm