queuez_update_frame.cpp 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #include "queuez_update_frame.h"
  2. #include <Windows.h>
  3. #include <algorithm>
  4. #include <array>
  5. #include "../../../../../middleware/bap/frame.h"
  6. #include "../../../../../middleware/secure_channel/runtime.h"
  7. namespace sunrise::server::bap::encrypted::push::queuez_frame {
  8. namespace {
  9. /** Unsolicited notifications have no request sequence to echo. */
  10. constexpr std::uint32_t kNotificationSequence = 0;
  11. /**
  12. * Wipes the part of one scratch buffer that may hold written bytes.
  13. * @param buffer Lock-owned scratch storage.
  14. * @param size Largest prefix that may hold transformed bytes.
  15. */
  16. void clear_prefix(std::span<std::byte> buffer, std::size_t size) noexcept {
  17. SecureZeroMemory(buffer.data(), (std::min)(buffer.size(), size));
  18. }
  19. } // namespace
  20. /** Securely clears raw and compressed object-staging prefixes. */
  21. void clear_object_storage(Scratch& scratch,
  22. std::size_t rawClearSize,
  23. std::size_t compressedClearSize) noexcept {
  24. clear_prefix(scratch.plaintext, rawClearSize);
  25. clear_prefix(scratch.sealed, compressedClearSize);
  26. }
  27. /** Appends one prepared family as a complete authenticated svc-123 frame. */
  28. bool append(Scratch& scratch,
  29. const middleware::queuez::Family& family,
  30. std::size_t rawClearSize,
  31. std::size_t compressedClearSize,
  32. std::span<const std::byte, state::kAesKeySize> key,
  33. std::span<const std::byte, state::kBapNonceSize> nonce,
  34. std::span<std::byte> response,
  35. std::size_t& written) noexcept {
  36. /** A staged queuez notification carries exactly one prepared family. */
  37. constexpr std::size_t familyCount = 1;
  38. const std::array families{family};
  39. std::size_t bodySize = 0;
  40. std::size_t payloadSize = 0;
  41. std::size_t sealedSize = 0;
  42. std::size_t frameSize = 0;
  43. const bool updateEncoded =
  44. written <= response.size()
  45. && middleware::queuez::encode_update(
  46. std::span(families).first(familyCount), scratch.responseBody, bodySize);
  47. // The update owns a byte copy, so borrowed object payloads can be erased before encryption.
  48. clear_object_storage(scratch, rawClearSize, compressedClearSize);
  49. const bool encoded =
  50. updateEncoded
  51. && middleware::bap::encode_notification_payload(
  52. middleware::bap::NotificationService::queuezUpdate,
  53. kNotificationSequence,
  54. std::span(scratch.responseBody).first(bodySize),
  55. scratch.responsePayload,
  56. payloadSize)
  57. && middleware::secure_channel::seal_frame(
  58. key,
  59. nonce,
  60. std::span(scratch.responsePayload).first(payloadSize),
  61. scratch.sealed,
  62. sealedSize)
  63. && middleware::bap::encode_frame(middleware::bap::FrameType::encrypted,
  64. std::span(scratch.sealed).first(sealedSize),
  65. response.subspan(written),
  66. frameSize);
  67. if (encoded) {
  68. written += frameSize;
  69. }
  70. clear_prefix(scratch.responseBody, bodySize);
  71. clear_prefix(scratch.responsePayload, payloadSize);
  72. clear_prefix(scratch.sealed, payloadSize + middleware::secure_channel::kFrameTagSize);
  73. return encoded;
  74. }
  75. } // namespace sunrise::server::bap::encrypted::push::queuez_frame