MCPcopy Create free account
hub / github.com/ClickHouse/ClickHouse / decrypt

Function decrypt

src/Compression/CompressionCodecEncrypted.cpp:183–234  ·  view source on GitHub ↗

Encrypt plaintext with particular algorithm and put result into ciphertext_and_tag. This function get key and nonce and encrypt text with their help. If something went wrong (can't init context or can't encrypt data) it throws exception. It returns length of encrypted text.

Source from the content-addressed store, hash-verified

181/// If something went wrong (can't init context or can't encrypt data) it throws exception.
182/// It returns length of encrypted text.
183size_t decrypt(std::string_view ciphertext, char * plaintext, EncryptionMethod method, const String & key, const String & nonce)
184{
185 int out_len = 0;
186 int plaintext_len = 0;
187
188 using EVP_CIPHER_CTX_ptr = std::unique_ptr<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)>;
189 const auto ctx = EVP_CIPHER_CTX_ptr(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);
190 if (!ctx)
191 throw Exception(ErrorCodes::OPENSSL_ERROR, "EVP_CIPHER_CTX_new failed: {}", getOpenSSLErrors());
192
193 using EVP_CIPHER_ptr = std::unique_ptr<EVP_CIPHER, decltype(&EVP_CIPHER_free)>;
194 const auto cipher = EVP_CIPHER_ptr(EVP_CIPHER_fetch(nullptr, getMethod(method), nullptr), EVP_CIPHER_free);
195 if (!cipher)
196 throw Exception(ErrorCodes::OPENSSL_ERROR, "EVP_CIPHER_fetch failed: {}", getOpenSSLErrors());
197
198 if (EVP_DecryptInit_ex(ctx.get(), cipher.get(), nullptr, nullptr, nullptr) != 1)
199 throw Exception(ErrorCodes::OPENSSL_ERROR, "EVP_DecryptInit_ex failed: {}", getOpenSSLErrors());
200
201 if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, static_cast<int32_t>(nonce.size()), nullptr) != 1)
202 throw Exception(ErrorCodes::OPENSSL_ERROR, "EVP_CIPHER_CTX_ctrl failed: {}", getOpenSSLErrors());
203
204 if (EVP_DecryptInit_ex(ctx.get(), nullptr, nullptr,
205 reinterpret_cast<const uint8_t*>(key.data()),
206 reinterpret_cast<const uint8_t *>(nonce.data())) != 1)
207 throw Exception(ErrorCodes::OPENSSL_ERROR, "EVP_DecryptInit_ex failed: {}", getOpenSSLErrors());
208
209 if (EVP_CIPHER_CTX_ctrl(ctx.get(),
210 EVP_CTRL_GCM_SET_TAG,
211 tag_size,
212 reinterpret_cast<uint8_t *>(const_cast<char *>(ciphertext.data())) + ciphertext.size() - tag_size) != 1)
213 throw Exception(ErrorCodes::OPENSSL_ERROR, "EVP_CIPHER_CTX_ctrl failed: {}", getOpenSSLErrors());
214
215 if (EVP_DecryptUpdate(ctx.get(),
216 reinterpret_cast<uint8_t *>(plaintext),
217 reinterpret_cast<int32_t *>(&out_len),
218 reinterpret_cast<const uint8_t *>(ciphertext.data()),
219 static_cast<int32_t>(ciphertext.size()) - tag_size) != 1)
220 throw Exception(ErrorCodes::OPENSSL_ERROR, "EVP_DecryptUpdate failed: {}", getOpenSSLErrors());
221
222 __msan_unpoison(plaintext, out_len); /// OpenSSL uses assembly which evades msan's analysis
223
224 plaintext_len = out_len;
225
226 if (EVP_DecryptFinal_ex(ctx.get(),
227 reinterpret_cast<uint8_t *>(plaintext) + out_len,
228 reinterpret_cast<int32_t *>(&out_len)) != 1)
229 throw Exception(ErrorCodes::OPENSSL_ERROR, "EVP_DecryptFinal_ex failed: {}", getOpenSSLErrors());
230
231 __msan_unpoison(plaintext, out_len); /// OpenSSL uses assembly which evades msan's analysis
232
233 return plaintext_len + out_len;
234}
235
236/// Register codec in factory
237void registerEncryptionCodec(CompressionCodecFactory & factory, EncryptionMethod Method)

Callers 1

doDecompressDataMethod · 0.85

Calls 6

getOpenSSLErrorsFunction · 0.85
ExceptionClass · 0.70
getMethodFunction · 0.70
getMethod · 0.45
sizeMethod · 0.45
dataMethod · 0.45

Tested by

no test coverage detected