#include "aes_gcm_encrypt.h" #include #include #include namespace sunrise::middleware::crypto::aes_gcm { /** Encrypts one buffer and returns its tag apart from the ciphertext. */ bool encrypt(std::span key, std::span nonce, std::span plaintext, std::span output, std::span tag) noexcept { if (plaintext.size() > (std::numeric_limits::max)() || output.size() < plaintext.size()) { return false; } BCRYPT_ALG_HANDLE algorithm = nullptr; if (BCryptOpenAlgorithmProvider(&algorithm, BCRYPT_AES_ALGORITHM, nullptr, 0) < 0) { return false; } BCRYPT_KEY_HANDLE symmetricKey = nullptr; bool sealed = false; if (BCryptSetProperty(algorithm, BCRYPT_CHAINING_MODE, reinterpret_cast(const_cast(BCRYPT_CHAIN_MODE_GCM)), sizeof(BCRYPT_CHAIN_MODE_GCM), 0) >= 0 && BCryptGenerateSymmetricKey(algorithm, &symmetricKey, nullptr, 0, reinterpret_cast(const_cast(key.data())), static_cast(key.size()), 0) >= 0) { BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authentication; BCRYPT_INIT_AUTH_MODE_INFO(authentication); authentication.pbNonce = reinterpret_cast(const_cast(nonce.data())); authentication.cbNonce = static_cast(nonce.size()); authentication.pbTag = reinterpret_cast(tag.data()); authentication.cbTag = static_cast(tag.size()); ULONG produced = 0; sealed = BCryptEncrypt(symmetricKey, reinterpret_cast(const_cast(plaintext.data())), static_cast(plaintext.size()), &authentication, nullptr, 0, reinterpret_cast(output.data()), static_cast(output.size()), &produced, 0) >= 0 && produced == plaintext.size(); BCryptDestroyKey(symmetricKey); } BCryptCloseAlgorithmProvider(algorithm, 0); return sealed; } } // namespace sunrise::middleware::crypto::aes_gcm