| // Copyright 2026 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "crypto/encrypt.h" | |
| #include "base/check.h" | |
| #include "base/check_op.h" | |
| #include "crypto/openssl_util.h" | |
| #include "third_party/boringssl/src/include/openssl/evp.h" | |
| #include "third_party/boringssl/src/include/openssl/rsa.h" | |
| #include "third_party/boringssl/src/include/openssl/sha.h" | |
| namespace crypto::encrypt { | |
| std::vector<uint8_t> Encrypt(EncryptionKind kind, | |
| const crypto::keypair::PublicKey& key, | |
| base::span<const uint8_t> plaintext) { | |
| crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | |
| CHECK_EQ(kind, RSA_OAEP_SHA1); | |
| // TODO(https://crbug.com/505090843): get rid of all the const_cast<> stuff | |
| // once the bssl API doesn't require it. | |
| EVP_PKEY* pkey = const_cast<EVP_PKEY*>(key.key()); | |
| bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(pkey, nullptr)); | |
| CHECK(ctx); | |
| CHECK(EVP_PKEY_encrypt_init(ctx.get())); | |
| CHECK(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING)); | |
| CHECK(EVP_PKEY_CTX_set_rsa_oaep_md(ctx.get(), EVP_sha1())); | |
| size_t outlen = 0; | |
| CHECK(EVP_PKEY_encrypt(ctx.get(), nullptr, &outlen, plaintext.data(), | |
| plaintext.size())); | |
| std::vector<uint8_t> ciphertext(outlen); | |
| CHECK(EVP_PKEY_encrypt(ctx.get(), ciphertext.data(), &outlen, | |
| plaintext.data(), plaintext.size())); | |
| ciphertext.resize(outlen); | |
| return ciphertext; | |
| } | |
| std::optional<std::vector<uint8_t>> Decrypt( | |
| EncryptionKind kind, | |
| const crypto::keypair::PrivateKey& key, | |
| base::span<const uint8_t> ciphertext) { | |
| crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | |
| if (kind != RSA_OAEP_SHA1) { | |
| return std::nullopt; | |
| } | |
| EVP_PKEY* pkey = const_cast<EVP_PKEY*>(key.key()); | |
| bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(pkey, nullptr)); | |
| CHECK(ctx); | |
| CHECK(EVP_PKEY_decrypt_init(ctx.get())); | |
| CHECK(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING)); | |
| CHECK(EVP_PKEY_CTX_set_rsa_oaep_md(ctx.get(), EVP_sha1())); | |
| size_t outlen = 0; | |
| if (!EVP_PKEY_decrypt(ctx.get(), nullptr, &outlen, ciphertext.data(), | |
| ciphertext.size())) { | |
| return std::nullopt; | |
| } | |
| std::vector<uint8_t> plaintext(outlen); | |
| if (!EVP_PKEY_decrypt(ctx.get(), plaintext.data(), &outlen, ciphertext.data(), | |
| ciphertext.size())) { | |
| return std::nullopt; | |
| } | |
| plaintext.resize(outlen); | |
| return plaintext; | |
| } | |
| size_t GetCiphertextSize(const crypto::keypair::PublicKey& key) { | |
| return EVP_PKEY_size(const_cast<EVP_PKEY*>(key.key())); | |
| } | |
| size_t GetCiphertextSize(const crypto::keypair::PrivateKey& key) { | |
| return EVP_PKEY_size(const_cast<EVP_PKEY*>(key.key())); | |
| } | |
| size_t GetMaxPlaintextSize(EncryptionKind kind, | |
| const crypto::keypair::PublicKey& key) { | |
| CHECK_EQ(kind, RSA_OAEP_SHA1); | |
| return GetCiphertextSize(key) - 2 - 2 * SHA_DIGEST_LENGTH; | |
| } | |
| size_t GetMaxPlaintextSize(EncryptionKind kind, | |
| const crypto::keypair::PrivateKey& key) { | |
| CHECK_EQ(kind, RSA_OAEP_SHA1); | |
| return GetCiphertextSize(key) - 2 - 2 * SHA_DIGEST_LENGTH; | |
| } | |
| } // namespace crypto::encrypt |