Fix RSA crypto.
GitOrigin-RevId: 8fd7350881e12ea81b05ab31c8756ff9f0a9305e
This commit is contained in:
parent
0d69e77689
commit
f615889953
@ -239,7 +239,6 @@ int pq_factorize(Slice pq_str, string *p_str, string *q_str) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** AES ***/
|
|
||||||
static void aes_ige_xcrypt(const UInt256 &aes_key, UInt256 *aes_iv, Slice from, MutableSlice to, bool encrypt_flag) {
|
static void aes_ige_xcrypt(const UInt256 &aes_key, UInt256 *aes_iv, Slice from, MutableSlice to, bool encrypt_flag) {
|
||||||
AES_KEY key;
|
AES_KEY key;
|
||||||
int err;
|
int err;
|
||||||
@ -388,7 +387,6 @@ void sha256_final(Sha256State *state, MutableSlice output) {
|
|||||||
state->impl.reset();
|
state->impl.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** md5 ***/
|
|
||||||
void md5(Slice input, MutableSlice output) {
|
void md5(Slice input, MutableSlice output) {
|
||||||
CHECK(output.size() >= MD5_DIGEST_LENGTH);
|
CHECK(output.size() >= MD5_DIGEST_LENGTH);
|
||||||
auto result = MD5(input.ubegin(), input.size(), output.ubegin());
|
auto result = MD5(input.ubegin(), input.size(), output.ubegin());
|
||||||
@ -440,6 +438,103 @@ void hmac_sha256(Slice key, Slice message, MutableSlice dest) {
|
|||||||
CHECK(len == dest.size());
|
CHECK(len == dest.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(const_cast<void *>(static_cast<const void *>(public_key.data())),
|
||||||
|
narrow_cast<int>(public_key.size()));
|
||||||
|
SCOPE_EXIT {
|
||||||
|
BIO_vfree(mem_bio);
|
||||||
|
};
|
||||||
|
|
||||||
|
EVP_PKEY *pkey = PEM_read_bio_PUBKEY(mem_bio, nullptr, nullptr, nullptr);
|
||||||
|
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);
|
||||||
|
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(const_cast<void *>(static_cast<const void *>(private_key.data())),
|
||||||
|
narrow_cast<int>(private_key.size()));
|
||||||
|
SCOPE_EXIT {
|
||||||
|
BIO_vfree(mem_bio);
|
||||||
|
};
|
||||||
|
|
||||||
|
EVP_PKEY *pkey = PEM_read_bio_PrivateKey(mem_bio, nullptr, nullptr, nullptr);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
BufferSlice res(outlen);
|
||||||
|
if (EVP_PKEY_decrypt(ctx, res.as_slice().ubegin(), &outlen, data.ubegin(), data.size()) <= 0) {
|
||||||
|
return Status::Error("Cannot decrypt");
|
||||||
|
}
|
||||||
|
return std::move(res);
|
||||||
|
}
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
namespace {
|
namespace {
|
||||||
std::vector<RwMutex> &openssl_mutexes() {
|
std::vector<RwMutex> &openssl_mutexes() {
|
||||||
@ -557,101 +652,4 @@ uint64 crc64(Slice data) {
|
|||||||
return crc64_partial(data, static_cast<uint64>(-1)) ^ static_cast<uint64>(-1);
|
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(const_cast<void *>(static_cast<const void *>(public_key.data())),
|
|
||||||
narrow_cast<int>(public_key.size()));
|
|
||||||
SCOPE_EXIT {
|
|
||||||
BIO_vfree(mem_bio);
|
|
||||||
};
|
|
||||||
|
|
||||||
EVP_PKEY *pkey = PEM_read_bio_PUBKEY(mem_bio, nullptr, nullptr, nullptr);
|
|
||||||
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);
|
|
||||||
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(const_cast<void *>(static_cast<const void *>(private_key.data())),
|
|
||||||
narrow_cast<int>(private_key.size()));
|
|
||||||
SCOPE_EXIT {
|
|
||||||
BIO_vfree(mem_bio);
|
|
||||||
};
|
|
||||||
|
|
||||||
EVP_PKEY *pkey = PEM_read_bio_PrivateKey(mem_bio, nullptr, nullptr, nullptr);
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
BufferSlice res(outlen);
|
|
||||||
if (EVP_PKEY_decrypt(ctx, res.as_slice().ubegin(), &outlen, data.ubegin(), data.size()) <= 0) {
|
|
||||||
return Status::Error("Cannot decrypt");
|
|
||||||
}
|
|
||||||
return std::move(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
Loading…
Reference in New Issue
Block a user