From f6158899530736bac555193a97176d5325c95a79 Mon Sep 17 00:00:00 2001 From: levlam Date: Tue, 27 Mar 2018 03:24:02 +0300 Subject: [PATCH] Fix RSA crypto. GitOrigin-RevId: 8fd7350881e12ea81b05ab31c8756ff9f0a9305e --- tdutils/td/utils/crypto.cpp | 196 ++++++++++++++++++------------------ 1 file changed, 97 insertions(+), 99 deletions(-) diff --git a/tdutils/td/utils/crypto.cpp b/tdutils/td/utils/crypto.cpp index 25e7679e2..e77e89181 100644 --- a/tdutils/td/utils/crypto.cpp +++ b/tdutils/td/utils/crypto.cpp @@ -239,7 +239,6 @@ int pq_factorize(Slice pq_str, string *p_str, string *q_str) { return 0; } -/*** AES ***/ static void aes_ige_xcrypt(const UInt256 &aes_key, UInt256 *aes_iv, Slice from, MutableSlice to, bool encrypt_flag) { AES_KEY key; int err; @@ -388,7 +387,6 @@ void sha256_final(Sha256State *state, MutableSlice output) { state->impl.reset(); } -/*** md5 ***/ void md5(Slice input, MutableSlice output) { CHECK(output.size() >= MD5_DIGEST_LENGTH); 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()); } +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 rsa_encrypt_pkcs1_oaep(Slice public_key, Slice data) { + BIO *mem_bio = BIO_new_mem_buf(const_cast(static_cast(public_key.data())), + narrow_cast(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 rsa_decrypt_pkcs1_oaep(Slice private_key, Slice data) { + BIO *mem_bio = BIO_new_mem_buf(const_cast(static_cast(private_key.data())), + narrow_cast(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 namespace { std::vector &openssl_mutexes() { @@ -557,101 +652,4 @@ uint64 crc64(Slice data) { return crc64_partial(data, static_cast(-1)) ^ static_cast(-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 rsa_encrypt_pkcs1_oaep(Slice public_key, Slice data) { - BIO *mem_bio = BIO_new_mem_buf(const_cast(static_cast(public_key.data())), - narrow_cast(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 rsa_decrypt_pkcs1_oaep(Slice private_key, Slice data) { - BIO *mem_bio = BIO_new_mem_buf(const_cast(static_cast(private_key.data())), - narrow_cast(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