forked from facebook/rocksdb
-
Notifications
You must be signed in to change notification settings - Fork 95
/
Copy pathencryption.h
139 lines (106 loc) · 3.98 KB
/
encryption.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0.
#pragma once
#ifdef OPENSSL
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <string>
#include "rocksdb/encryption.h"
#include "rocksdb/env_encryption.h"
#include "util/string_util.h"
namespace ROCKSDB_NAMESPACE {
namespace encryption {
#if OPENSSL_VERSION_NUMBER < 0x01010000f
#define InitCipherContext(ctx) \
EVP_CIPHER_CTX ctx##_var; \
ctx = &ctx##_var; \
EVP_CIPHER_CTX_init(ctx);
// do nothing
#define FreeCipherContext(ctx)
#else
#define InitCipherContext(ctx) \
ctx = EVP_CIPHER_CTX_new(); \
if (ctx != nullptr) { \
if (EVP_CIPHER_CTX_reset(ctx) != 1) { \
ctx = nullptr; \
} \
}
#define FreeCipherContext(ctx) EVP_CIPHER_CTX_free(ctx);
#endif
// TODO: OpenSSL Lib does not export SM4_BLOCK_SIZE by now.
// Need to remove SM4_BLOCK_Size once Openssl lib support the definition.
// SM4 uses 128-bit block size as AES.
// Ref:
// https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/include/crypto/sm4.h#L24
#define SM4_BLOCK_SIZE 16
class AESCTRCipherStream : public BlockAccessCipherStream {
public:
AESCTRCipherStream(const EVP_CIPHER* cipher, const std::string& key,
uint64_t iv_high, uint64_t iv_low)
: cipher_(cipher),
key_(key),
initial_iv_high_(iv_high),
initial_iv_low_(iv_low) {}
~AESCTRCipherStream() = default;
size_t BlockSize() override {
// Openssl support SM4 after 1.1.1 release version.
#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_SM4)
if (EVP_CIPHER_nid(cipher_) == NID_sm4_ctr) {
return SM4_BLOCK_SIZE;
}
#endif
return AES_BLOCK_SIZE; // 16
}
Status Encrypt(uint64_t file_offset, char* data, size_t data_size) override {
return Cipher(file_offset, data, data_size, true /*is_encrypt*/);
}
Status Decrypt(uint64_t file_offset, char* data, size_t data_size) override {
return Cipher(file_offset, data, data_size, false /*is_encrypt*/);
}
protected:
// Following methods required by BlockAccessCipherStream is unused.
void AllocateScratch(std::string& /*scratch*/) override {
// should not be called.
assert(false);
}
Status EncryptBlock(uint64_t /*block_index*/, char* /*data*/,
char* /*scratch*/) override {
return Status::NotSupported("EncryptBlock should not be called.");
}
Status DecryptBlock(uint64_t /*block_index*/, char* /*data*/,
char* /*scratch*/) override {
return Status::NotSupported("DecryptBlock should not be called.");
}
private:
Status Cipher(uint64_t file_offset, char* data, size_t data_size,
bool is_encrypt);
const EVP_CIPHER* cipher_;
const std::string key_;
const uint64_t initial_iv_high_;
const uint64_t initial_iv_low_;
};
extern Status NewAESCTRCipherStream(
EncryptionMethod method, const std::string& key, const std::string& iv,
std::unique_ptr<AESCTRCipherStream>* result);
class AESEncryptionProvider : public EncryptionProvider {
public:
AESEncryptionProvider(KeyManager* key_manager) : key_manager_(key_manager) {}
virtual ~AESEncryptionProvider() = default;
const char* Name() const override { return "AESEncryptionProvider"; }
size_t GetPrefixLength() const override { return 0; }
Status CreateNewPrefix(const std::string& /*fname*/, char* /*prefix*/,
size_t /*prefix_length*/) const override {
return Status::OK();
}
Status AddCipher(const std::string& /*descriptor*/, const char* /*cipher*/,
size_t /*len*/, bool /*for_write*/) override {
return Status::NotSupported();
}
Status CreateCipherStream(
const std::string& fname, const EnvOptions& options, Slice& prefix,
std::unique_ptr<BlockAccessCipherStream>* result) override;
private:
KeyManager* key_manager_;
};
} // namespace encryption
} // namespace ROCKSDB_NAMESPACE
#endif // OPENSSL