RSA encrypt/decrypt and warning fixes.

GitOrigin-RevId: 6d556509d911678c1dd7d489132c07f942f3be0f
This commit is contained in:
levlam 2018-03-26 21:14:15 +03:00
parent 372196280c
commit b6637ccfc5
4 changed files with 59 additions and 23 deletions

View File

@ -43,7 +43,7 @@ Result<ValueHash> calc_value_hash(DataView &data_view) {
}
BufferSlice gen_random_prefix(int64 data_size) {
BufferSlice buff(((32 + 15 + data_size) & -16) - data_size);
BufferSlice buff(narrow_cast<size_t>(((32 + 15 + data_size) & -16) - data_size));
Random::secure_bytes(buff.as_slice());
buff.as_slice()[0] = narrow_cast<uint8>(buff.size());
CHECK((buff.size() + data_size) % 16 == 0);
@ -58,7 +58,7 @@ int64 FileDataView::size() {
}
Result<BufferSlice> FileDataView::pread(int64 offset, int64 size) {
auto slice = BufferSlice(size);
auto slice = BufferSlice(narrow_cast<size_t>(size));
TRY_RESULT(actual_size, fd_.pread(slice.as_slice(), offset));
if (static_cast<int64>(actual_size) != size) {
return Status::Error("Not enough data in file");
@ -69,14 +69,14 @@ Result<BufferSlice> FileDataView::pread(int64 offset, int64 size) {
BufferSliceDataView::BufferSliceDataView(BufferSlice buffer_slice) : buffer_slice_(std::move(buffer_slice)) {
}
int64 BufferSliceDataView::size() {
return buffer_slice_.size();
return narrow_cast<int64>(buffer_slice_.size());
}
Result<BufferSlice> BufferSliceDataView::pread(int64 offset, int64 size) {
auto end_offset = size + offset;
if (this->size() < end_offset) {
return Status::Error("Not enough data in BufferSlice");
}
return BufferSlice(buffer_slice_.as_slice().substr(offset, size));
return BufferSlice(buffer_slice_.as_slice().substr(narrow_cast<size_t>(offset), narrow_cast<size_t>(size)));
}
ConcatDataView::ConcatDataView(DataView &left, DataView &right) : left_(left), right_(right) {

View File

@ -15,14 +15,14 @@
#if TD_HAVE_OPENSSL
#include <openssl/aes.h>
#include <openssl/engine.h>
#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#endif
#if TD_HAVE_ZLIB
@ -557,8 +557,17 @@ uint64 crc64(Slice data) {
return crc64_partial(data, static_cast<uint64>(-1)) ^ static_cast<uint64>(-1);
}
static int get_evp_pkey_type(EVP_PKEY *pkey) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
return EVP_PKEY_type(pkey->type);
#else
return EVP_PKEY_base_id(pkey);
#endif
}
Result<BufferSlice> rsa_encrypt_pkcs1_oaep(Slice public_key, Slice data) {
BIO *mem_bio = BIO_new_mem_buf(public_key.data(), narrow_cast<int>(public_key.size()));
BIO *mem_bio = BIO_new_mem_buf(const_cast<void *>(static_cast<const void *>(public_key.data())),
narrow_cast<int>(public_key.size()));
SCOPE_EXIT {
BIO_vfree(mem_bio);
};
@ -567,30 +576,43 @@ Result<BufferSlice> rsa_encrypt_pkcs1_oaep(Slice public_key, Slice data) {
if (!pkey) {
return Status::Error("Cannot read public key");
}
SCOPE_EXIT {
EVP_PKEY_free(pkey);
};
if (get_evp_pkey_type(pkey) != EVP_PKEY_RSA) {
return Status::Error("Wrong key type, expected RSA");
}
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, nullptr);
if (!ctx) {
return Status::Error("Cannot create EVP_PKEY_CTX");
}
SCOPE_EXIT {
EVP_PKEY_CTX_free(ctx);
};
if (EVP_PKEY_encrypt_init(ctx) <= 0) {
return Status::Error("Cannot init EVP_PKEY_CTX");
}
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
return Status::Error("Cannot set RSA_PKCS1_OAEP padding in EVP_PKEY_CTX");
}
size_t outlen;
if (EVP_PKEY_encrypt(ctx, nullptr, &outlen, data.ubegin(), data.size()) <= 0) {
return Status::Error("Cannot calculate encrypted length");
}
BufferSlice res(outlen);
if (EVP_PKEY_encrypt(ctx, res.as_slice().ubegin(), &outlen, data.ubegin(), data.size()) <= 0) {
ERR_print_errors_fp(stderr);
// ERR_print_errors_fp(stderr);
return Status::Error("Cannot encrypt");
}
return std::move(res);
}
Result<BufferSlice> rsa_decrypt_pkcs1_oaep(Slice private_key, Slice data) {
BIO *mem_bio = BIO_new_mem_buf(private_key.data(), narrow_cast<int>(private_key.size()));
BIO *mem_bio = BIO_new_mem_buf(const_cast<void *>(static_cast<const void *>(private_key.data())),
narrow_cast<int>(private_key.size()));
SCOPE_EXIT {
BIO_vfree(mem_bio);
};
@ -599,16 +621,28 @@ Result<BufferSlice> rsa_decrypt_pkcs1_oaep(Slice private_key, Slice data) {
if (!pkey) {
return Status::Error("Cannot read private key");
}
SCOPE_EXIT {
EVP_PKEY_free(pkey);
};
if (get_evp_pkey_type(pkey) != EVP_PKEY_RSA) {
return Status::Error("Wrong key type, expected RSA");
}
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, nullptr);
if (!ctx) {
return Status::Error("Cannot create EVP_PKEY_CTX");
}
SCOPE_EXIT {
EVP_PKEY_CTX_free(ctx);
};
if (EVP_PKEY_decrypt_init(ctx) <= 0) {
return Status::Error("Cannot init EVP_PKEY_CTX");
}
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
return Status::Error("Cannot set RSA_PKCS1_OAEP padding in EVP_PKEY_CTX");
}
size_t outlen;
if (EVP_PKEY_decrypt(ctx, nullptr, &outlen, data.ubegin(), data.size()) <= 0) {
return Status::Error("Cannot calculate decrypted length");

View File

@ -6,9 +6,9 @@
//
#pragma once
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include "td/utils/buffer.h"
#include "td/utils/Status.h"
namespace td {
@ -85,7 +85,7 @@ void hmac_sha256(Slice key, Slice message, MutableSlice dest);
// Interface may be improved
Result<BufferSlice> rsa_encrypt_pkcs1_oaep(Slice public_key, Slice data);
Result<BufferSlice> rsa_decrypt_pkcs1_oaep(Slice public_key, Slice data);
Result<BufferSlice> rsa_decrypt_pkcs1_oaep(Slice private_key, Slice data);
void init_openssl_threads();
#endif

View File

@ -29,20 +29,22 @@ TEST(SecureStorage, simple) {
BufferSlice value("Small tale about cucumbers");
auto value_secret = Secret::create_new();
auto value_view = BufferSliceDataView(value.copy());
BufferSlice prefix = gen_random_prefix(value_view.size());
auto prefix_view = BufferSliceDataView(std::move(prefix));
auto full_value_view = ConcatDataView(prefix_view, value_view);
auto hash = calc_value_hash(full_value_view).move_as_ok();
{
auto value_view = BufferSliceDataView(value.copy());
BufferSlice prefix = gen_random_prefix(value_view.size());
auto prefix_view = BufferSliceDataView(std::move(prefix));
auto full_value_view = ConcatDataView(prefix_view, value_view);
auto hash = calc_value_hash(full_value_view).move_as_ok();
Encryptor encryptor(calc_aes_cbc_state(PSLICE() << value_secret.as_slice() << hash.as_slice()), full_value_view);
auto encrypted_value = encryptor.pread(0, encryptor.size()).move_as_ok();
Encryptor encryptor(calc_aes_cbc_state(PSLICE() << value_secret.as_slice() << hash.as_slice()), full_value_view);
auto encrypted_value = encryptor.pread(0, encryptor.size()).move_as_ok();
Decryptor decryptor(calc_aes_cbc_state(PSLICE() << value_secret.as_slice() << hash.as_slice()));
auto res = decryptor.append(encrypted_value.copy()).move_as_ok();
auto decrypted_hash = decryptor.finish().ok();
ASSERT_TRUE(decrypted_hash.as_slice() == hash.as_slice());
ASSERT_TRUE(res.as_slice() == value.as_slice());
Decryptor decryptor(calc_aes_cbc_state(PSLICE() << value_secret.as_slice() << hash.as_slice()));
auto res = decryptor.append(encrypted_value.copy()).move_as_ok();
auto decrypted_hash = decryptor.finish().ok();
ASSERT_TRUE(decrypted_hash.as_slice() == hash.as_slice());
ASSERT_TRUE(res.as_slice() == value.as_slice());
}
{
auto encrypted_value = encrypt_value(value_secret, value.as_slice()).move_as_ok();