| 503 | // In case the op data is not encrypted, simply read the operands and the zero fill flag. |
| 504 | // Otherwise, decrypt the op type and data. |
| 505 | ACTOR static Future<Standalone<StringRef>> readOpData(KeyValueStoreMemory* self, |
| 506 | OpHeader* h, |
| 507 | bool* isZeroFilled, |
| 508 | int* zeroFillSize) { |
| 509 | // Metadata op types to be excluded from encryption. |
| 510 | static std::unordered_set<OpType> metaOps = { OpSnapshotEnd, OpSnapshotAbort, OpCommit, OpRollback }; |
| 511 | if (metaOps.count((OpType)h->op) == 0) { |
| 512 | // It is not supported to open an encrypted store as unencrypted, or vice-versa. |
| 513 | ASSERT_EQ(h->op == OpEncrypted, self->enableEncryption); |
| 514 | } |
| 515 | state int remainingBytes = h->len1 + h->len2 + 1; |
| 516 | if (h->op == OpEncrypted) { |
| 517 | // encryption header, plus the real (encrypted) op type |
| 518 | remainingBytes += BlobCipherEncryptHeader::headerSize + sizeof(int); |
| 519 | } |
| 520 | state Standalone<StringRef> data = wait(self->log->readNext(remainingBytes)); |
| 521 | ASSERT(data.size() <= remainingBytes); |
| 522 | *zeroFillSize = remainingBytes - data.size(); |
| 523 | if (*zeroFillSize == 0) { |
| 524 | *isZeroFilled = (data[data.size() - 1] == 0); |
| 525 | } |
| 526 | if (h->op != OpEncrypted || *zeroFillSize > 0 || *isZeroFilled) { |
| 527 | return data; |
| 528 | } |
| 529 | state BlobCipherEncryptHeader cipherHeader = *(BlobCipherEncryptHeader*)data.begin(); |
| 530 | TextAndHeaderCipherKeys cipherKeys = wait(getEncryptCipherKeys(self->db, cipherHeader)); |
| 531 | DecryptBlobCipherAes256Ctr cipher(cipherKeys.cipherTextKey, cipherKeys.cipherHeaderKey, cipherHeader.iv); |
| 532 | Arena arena; |
| 533 | StringRef plaintext = cipher |
| 534 | .decrypt(data.begin() + BlobCipherEncryptHeader::headerSize, |
| 535 | sizeof(int) + h->len1 + h->len2, |
| 536 | cipherHeader, |
| 537 | arena) |
| 538 | ->toStringRef(); |
| 539 | h->op = *(int*)plaintext.begin(); |
| 540 | return Standalone<StringRef>(plaintext.substr(sizeof(int)), arena); |
| 541 | } |
| 542 | |
| 543 | ACTOR static Future<Void> recover(KeyValueStoreMemory* self, bool exactRecovery) { |
| 544 | loop { |