| 99 | } |
| 100 | |
| 101 | ACTOR static Future<Void> write(Reference<AsyncFileEncrypted> self, void const* data, int length, int64_t offset) { |
| 102 | ASSERT(self->mode == AsyncFileEncrypted::Mode::APPEND_ONLY); |
| 103 | // All writes must append to the end of the file: |
| 104 | ASSERT_EQ(offset, self->currentBlock * FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE + self->offsetInBlock); |
| 105 | state unsigned char const* input = reinterpret_cast<unsigned char const*>(data); |
| 106 | while (length > 0) { |
| 107 | const auto chunkSize = std::min(length, FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE - self->offsetInBlock); |
| 108 | Arena arena; |
| 109 | auto encrypted = self->encryptor->encrypt(input, chunkSize, arena); |
| 110 | std::copy(encrypted.begin(), encrypted.end(), &self->writeBuffer[self->offsetInBlock]); |
| 111 | offset += encrypted.size(); |
| 112 | self->offsetInBlock += chunkSize; |
| 113 | length -= chunkSize; |
| 114 | input += chunkSize; |
| 115 | if (self->offsetInBlock == FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE) { |
| 116 | wait(self->writeLastBlockToFile()); |
| 117 | self->offsetInBlock = 0; |
| 118 | ASSERT_LT(self->currentBlock, std::numeric_limits<uint32_t>::max()); |
| 119 | ++self->currentBlock; |
| 120 | self->encryptor = std::make_unique<EncryptionStreamCipher>(StreamCipherKey::getGlobalCipherKey(), |
| 121 | self->getIV(self->currentBlock)); |
| 122 | } |
| 123 | } |
| 124 | return Void(); |
| 125 | } |
| 126 | |
| 127 | ACTOR static Future<Void> sync(Reference<AsyncFileEncrypted> self) { |
| 128 | ASSERT(self->mode == AsyncFileEncrypted::Mode::APPEND_ONLY); |