/*
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <keymaster/km_openssl/rsa_operation.h>

#include <limits.h>

#include <openssl/err.h>

#include <keymaster/km_openssl/openssl_err.h>
#include <keymaster/km_openssl/openssl_utils.h>
#include <keymaster/km_openssl/rsa_key.h>
#include <keymaster/logger.h>

namespace keymaster {

const size_t kPssOverhead = 2;

// Overhead for PKCS#1 v1.5 signature padding of undigested messages.  Digested messages have
// additional overhead, for the digest algorithmIdentifier required by PKCS#1.
const size_t kPkcs1UndigestedSignaturePaddingOverhead = 11;

/* static */
EVP_PKEY* RsaOperationFactory::GetRsaKey(const Key& key, keymaster_error_t* error) {
    const RsaKey& rsa_key = static_cast<const RsaKey&>(key);
    if (!rsa_key.key()) {
        *error = KM_ERROR_UNKNOWN_ERROR;
        return nullptr;
    }

    EVP_PKEY_Ptr pkey(rsa_key.InternalToEvp());
    if (pkey.get() == nullptr) {
        *error = KM_ERROR_UNKNOWN_ERROR;
        return nullptr;
    }
    return pkey.release();
}

static const keymaster_digest_t supported_digests[] = {
    KM_DIGEST_NONE,      KM_DIGEST_MD5,       KM_DIGEST_SHA1,     KM_DIGEST_SHA_2_224,
    KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};

const keymaster_digest_t* RsaOperationFactory::SupportedDigests(size_t* digest_count) const {
    *digest_count = array_length(supported_digests);
    return supported_digests;
}

RsaOperation* RsaOperationFactory::CreateRsaOperation(Key&& key,
                                                      const AuthorizationSet& begin_params,
                                                      keymaster_error_t* error) {
    keymaster_padding_t padding;
    if (!GetAndValidatePadding(begin_params, key, &padding, error)) return nullptr;

    bool require_digest = (purpose() == KM_PURPOSE_SIGN || purpose() == KM_PURPOSE_VERIFY ||
                           padding == KM_PAD_RSA_OAEP);

    keymaster_digest_t digest = KM_DIGEST_NONE;

    if (require_digest && !GetAndValidateDigest(begin_params, key, &digest, error, true)) {
        return nullptr;
    }

    UniquePtr<EVP_PKEY, EVP_PKEY_Delete> rsa(GetRsaKey(key, error));
    if (!rsa.get()) return nullptr;

    RsaOperation* op = InstantiateOperation(key.hw_enforced_move(), key.sw_enforced_move(), digest,
                                            padding, rsa.release());
    if (!op) *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
    return op;
}

static const keymaster_padding_t supported_sig_padding[] = {KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN,
                                                            KM_PAD_RSA_PSS};
const keymaster_padding_t*
RsaDigestingOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
    *padding_mode_count = array_length(supported_sig_padding);
    return supported_sig_padding;
}

RsaOperation* RsaCryptingOperationFactory::CreateRsaOperation(Key&& key,
                                                              const AuthorizationSet& begin_params,
                                                              keymaster_error_t* error) {
    keymaster_digest_t mgf_digest = KM_DIGEST_NONE;
    key.authorizations().GetTagValue(TAG_RSA_OAEP_MGF_DIGEST, &mgf_digest);
    *error = GetAndValidateMgfDigest(begin_params, key, &mgf_digest);
    if (*error != KM_ERROR_OK) return nullptr;
    UniquePtr<RsaOperation> op(
        RsaOperationFactory::CreateRsaOperation(move(key), begin_params, error));
    if (op.get()) {
        switch (op->padding()) {
        case KM_PAD_NONE:
        case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
            if (op->digest() != KM_DIGEST_NONE) {
                *error = KM_ERROR_INCOMPATIBLE_DIGEST;
                return nullptr;
            }
            break;

        case KM_PAD_RSA_OAEP:
            if (op->digest() == KM_DIGEST_NONE) {
                *error = KM_ERROR_INCOMPATIBLE_DIGEST;
                return nullptr;
            }
            static_cast<RsaCryptOperation*>(op.get())->setOaepMgfDigest(mgf_digest);
            break;

        default:
            *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
            return nullptr;
        }
    }
    return op.release();
}

keymaster_error_t RsaCryptingOperationFactory::GetAndValidateMgfDigest(
    const AuthorizationSet& begin_params, const Key& key, keymaster_digest_t* digest) const {
    *digest = KM_DIGEST_SHA1;
    if (!begin_params.Contains(TAG_PADDING, KM_PAD_RSA_OAEP)) {
        *digest = KM_DIGEST_NONE;
        return KM_ERROR_OK;
    }
    // If begin params does not specify any mgf digest
    if (!begin_params.GetTagValue(TAG_RSA_OAEP_MGF_DIGEST, digest)) {
        // And the authorizations has MGF Digest tag specified.
        if (key.authorizations().GetTagCount(TAG_RSA_OAEP_MGF_DIGEST) > 0) {
            // And key authorizations does not contain SHA1 for Mgf digest.
            if (!key.authorizations().Contains(TAG_RSA_OAEP_MGF_DIGEST, KM_DIGEST_SHA1)) {
                // Then it is an error.
                LOG_E("%d MGF digests specified in begin params and SHA1 not authorized",
                      begin_params.GetTagCount(TAG_RSA_OAEP_MGF_DIGEST));
                return KM_ERROR_UNSUPPORTED_MGF_DIGEST;
            }
        }
    } else if (!supported(*digest) || (*digest == KM_DIGEST_NONE)) {
        LOG_E("MGF Digest %d not supported", *digest);
        return KM_ERROR_UNSUPPORTED_MGF_DIGEST;
    } else if (!key.authorizations().Contains(TAG_RSA_OAEP_MGF_DIGEST, *digest)) {
        LOG_E("MGF Digest %d was specified, but not authorized by key", *digest);
        return KM_ERROR_INCOMPATIBLE_MGF_DIGEST;
    }
    return KM_ERROR_OK;
}

static const keymaster_padding_t supported_crypt_padding[] = {KM_PAD_NONE, KM_PAD_RSA_OAEP,
                                                              KM_PAD_RSA_PKCS1_1_5_ENCRYPT};
const keymaster_padding_t*
RsaCryptingOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
    *padding_mode_count = array_length(supported_crypt_padding);
    return supported_crypt_padding;
}

RsaOperation::~RsaOperation() {
    if (rsa_key_ != nullptr) EVP_PKEY_free(rsa_key_);
}

keymaster_error_t RsaOperation::Begin(const AuthorizationSet& /* input_params */,
                                      AuthorizationSet* /* output_params */) {
    auto rc = GenerateRandom(reinterpret_cast<uint8_t*>(&operation_handle_),
                             (size_t)sizeof(operation_handle_));
    if (rc != KM_ERROR_OK) return rc;

    return InitDigest();
}

keymaster_error_t RsaOperation::Update(const AuthorizationSet& /* additional_params */,
                                       const Buffer& input, AuthorizationSet* /* output_params */,
                                       Buffer* /* output */, size_t* input_consumed) {
    assert(input_consumed);
    switch (purpose()) {
    default:
        return KM_ERROR_UNIMPLEMENTED;
    case KM_PURPOSE_SIGN:
    case KM_PURPOSE_VERIFY:
    case KM_PURPOSE_ENCRYPT:
    case KM_PURPOSE_DECRYPT:
        return StoreData(input, input_consumed);
    }
}

keymaster_error_t RsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
    assert(input_consumed);

    if (!data_.reserve(EVP_PKEY_size(rsa_key_))) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    // If the write fails, it's because input length exceeds key size.
    if (!data_.write(input.peek_read(), input.available_read())) {
        LOG_E("Input too long: cannot operate on %u bytes of data with %u-byte RSA key",
              input.available_read() + data_.available_read(), EVP_PKEY_size(rsa_key_));
        return KM_ERROR_INVALID_INPUT_LENGTH;
    }

    *input_consumed = input.available_read();
    return KM_ERROR_OK;
}

keymaster_error_t RsaOperation::SetRsaPaddingInEvpContext(EVP_PKEY_CTX* pkey_ctx, bool signing) {
    keymaster_error_t error;
    int openssl_padding = GetOpensslPadding(&error);
    if (error != KM_ERROR_OK) return error;

    if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, openssl_padding) <= 0)
        return TranslateLastOpenSslError();

    if (signing && openssl_padding == RSA_PKCS1_PSS_PADDING) {
        // Also need to set the length of the salt used in the padding generation.  We set it equal
        // to the length of the selected digest.
        assert(digest_algorithm_);
        if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, EVP_MD_size(digest_algorithm_)) <= 0)
            return TranslateLastOpenSslError();
    }

    return KM_ERROR_OK;
}

keymaster_error_t RsaOperation::InitDigest() {
    if (digest_ == KM_DIGEST_NONE) {
        if (require_digest()) return KM_ERROR_INCOMPATIBLE_DIGEST;
        return KM_ERROR_OK;
    }
    digest_algorithm_ = KmDigestToEvpDigest(digest_);
    if (digest_algorithm_ == nullptr) {
        return KM_ERROR_UNSUPPORTED_DIGEST;
    }
    return KM_ERROR_OK;
}

RsaDigestingOperation::RsaDigestingOperation(AuthorizationSet&& hw_enforced,
                                             AuthorizationSet&& sw_enforced,
                                             keymaster_purpose_t purpose, keymaster_digest_t digest,
                                             keymaster_padding_t padding, EVP_PKEY* key)
    : RsaOperation(move(hw_enforced), move(sw_enforced), purpose, digest, padding, key) {
    EVP_MD_CTX_init(&digest_ctx_);
}
RsaDigestingOperation::~RsaDigestingOperation() {
    EVP_MD_CTX_cleanup(&digest_ctx_);
}

int RsaDigestingOperation::GetOpensslPadding(keymaster_error_t* error) {
    *error = KM_ERROR_OK;
    switch (padding_) {
    case KM_PAD_NONE:
        return RSA_NO_PADDING;
    case KM_PAD_RSA_PKCS1_1_5_SIGN:
        return RSA_PKCS1_PADDING;
    case KM_PAD_RSA_PSS:
        if (digest_ == KM_DIGEST_NONE) {
            *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
            return -1;
        }
        if (EVP_MD_size(digest_algorithm_) * 2 + kPssOverhead > (size_t)EVP_PKEY_size(rsa_key_)) {
            LOG_E("Input too long: %d-byte digest cannot be used with %d-byte RSA key in PSS "
                  "padding mode",
                  EVP_MD_size(digest_algorithm_), EVP_PKEY_size(rsa_key_));
            *error = KM_ERROR_INCOMPATIBLE_DIGEST;
            return -1;
        }
        return RSA_PKCS1_PSS_PADDING;
    default:
        return -1;
    }
}

keymaster_error_t RsaSignOperation::Begin(const AuthorizationSet& input_params,
                                          AuthorizationSet* output_params) {
    keymaster_error_t error = RsaDigestingOperation::Begin(input_params, output_params);
    if (error != KM_ERROR_OK) return error;

    if (digest_ == KM_DIGEST_NONE) return KM_ERROR_OK;

    EVP_PKEY_CTX* pkey_ctx;
    if (EVP_DigestSignInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
                           rsa_key_) != 1)
        return TranslateLastOpenSslError();
    return SetRsaPaddingInEvpContext(pkey_ctx, true /* signing */);
}

keymaster_error_t RsaSignOperation::Update(const AuthorizationSet& additional_params,
                                           const Buffer& input, AuthorizationSet* output_params,
                                           Buffer* output, size_t* input_consumed) {
    if (digest_ == KM_DIGEST_NONE)
        // Just buffer the data.
        return RsaOperation::Update(additional_params, input, output_params, output,
                                    input_consumed);

    if (EVP_DigestSignUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
        return TranslateLastOpenSslError();
    *input_consumed = input.available_read();
    return KM_ERROR_OK;
}

keymaster_error_t RsaSignOperation::Finish(const AuthorizationSet& additional_params,
                                           const Buffer& input, const Buffer& /* signature */,
                                           AuthorizationSet* /* output_params */, Buffer* output) {
    assert(output);

    keymaster_error_t error = UpdateForFinish(additional_params, input);
    if (error != KM_ERROR_OK) return error;

    if (digest_ == KM_DIGEST_NONE)
        return SignUndigested(output);
    else
        return SignDigested(output);
}

static keymaster_error_t zero_pad_left(UniquePtr<uint8_t[]>* dest, size_t padded_len, Buffer& src) {
    assert(padded_len > src.available_read());

    dest->reset(new (std::nothrow) uint8_t[padded_len]);
    if (!dest->get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;

    size_t padding_len = padded_len - src.available_read();
    memset(dest->get(), 0, padding_len);
    if (!src.read(dest->get() + padding_len, src.available_read())) return KM_ERROR_UNKNOWN_ERROR;

    return KM_ERROR_OK;
}

keymaster_error_t RsaSignOperation::SignUndigested(Buffer* output) {
    UniquePtr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(rsa_key_)));
    if (!rsa.get()) return TranslateLastOpenSslError();

    if (!output->Reinitialize(RSA_size(rsa.get()))) return KM_ERROR_MEMORY_ALLOCATION_FAILED;

    size_t key_len = EVP_PKEY_size(rsa_key_);
    int bytes_encrypted;
    switch (padding_) {
    case KM_PAD_NONE: {
        const uint8_t* to_encrypt = data_.peek_read();
        UniquePtr<uint8_t[]> zero_padded;
        if (data_.available_read() > key_len) {
            return KM_ERROR_INVALID_INPUT_LENGTH;
        } else if (data_.available_read() < key_len) {
            keymaster_error_t error = zero_pad_left(&zero_padded, key_len, data_);
            if (error != KM_ERROR_OK) return error;
            to_encrypt = zero_padded.get();
        }
        bytes_encrypted = RSA_private_encrypt(key_len, to_encrypt, output->peek_write(), rsa.get(),
                                              RSA_NO_PADDING);
        break;
    }
    case KM_PAD_RSA_PKCS1_1_5_SIGN:
        // Does PKCS1 padding without digesting even make sense?  Dunno.  We'll support it.
        if (data_.available_read() + kPkcs1UndigestedSignaturePaddingOverhead > key_len) {
            LOG_E("Input too long: cannot sign %u-byte message with PKCS1 padding with %u-bit key",
                  data_.available_read(), EVP_PKEY_size(rsa_key_) * 8);
            return KM_ERROR_INVALID_INPUT_LENGTH;
        }
        bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
                                              output->peek_write(), rsa.get(), RSA_PKCS1_PADDING);
        break;

    default:
        return KM_ERROR_UNSUPPORTED_PADDING_MODE;
    }

    if (bytes_encrypted <= 0) return TranslateLastOpenSslError();
    if (!output->advance_write(bytes_encrypted)) return KM_ERROR_UNKNOWN_ERROR;
    return KM_ERROR_OK;
}

keymaster_error_t RsaSignOperation::SignDigested(Buffer* output) {
    size_t siglen;
    if (EVP_DigestSignFinal(&digest_ctx_, nullptr /* signature */, &siglen) != 1)
        return TranslateLastOpenSslError();

    if (!output->Reinitialize(siglen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;

    if (EVP_DigestSignFinal(&digest_ctx_, output->peek_write(), &siglen) <= 0)
        return TranslateLastOpenSslError();
    if (!output->advance_write(siglen)) return KM_ERROR_UNKNOWN_ERROR;

    return KM_ERROR_OK;
}

keymaster_error_t RsaVerifyOperation::Begin(const AuthorizationSet& input_params,
                                            AuthorizationSet* output_params) {
    keymaster_error_t error = RsaDigestingOperation::Begin(input_params, output_params);
    if (error != KM_ERROR_OK) return error;

    if (digest_ == KM_DIGEST_NONE) return KM_ERROR_OK;

    EVP_PKEY_CTX* pkey_ctx;
    if (EVP_DigestVerifyInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr, rsa_key_) != 1)
        return TranslateLastOpenSslError();
    return SetRsaPaddingInEvpContext(pkey_ctx, false /* signing */);
}

keymaster_error_t RsaVerifyOperation::Update(const AuthorizationSet& additional_params,
                                             const Buffer& input, AuthorizationSet* output_params,
                                             Buffer* output, size_t* input_consumed) {
    if (digest_ == KM_DIGEST_NONE)
        // Just buffer the data.
        return RsaOperation::Update(additional_params, input, output_params, output,
                                    input_consumed);

    if (EVP_DigestVerifyUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
        return TranslateLastOpenSslError();
    *input_consumed = input.available_read();
    return KM_ERROR_OK;
}

keymaster_error_t RsaVerifyOperation::Finish(const AuthorizationSet& additional_params,
                                             const Buffer& input, const Buffer& signature,
                                             AuthorizationSet* /* output_params */,
                                             Buffer* /* output */) {
    keymaster_error_t error = UpdateForFinish(additional_params, input);
    if (error != KM_ERROR_OK) return error;

    if (digest_ == KM_DIGEST_NONE)
        return VerifyUndigested(signature);
    else
        return VerifyDigested(signature);
}

keymaster_error_t RsaVerifyOperation::VerifyUndigested(const Buffer& signature) {
    UniquePtr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(rsa_key_)));
    if (!rsa.get()) return KM_ERROR_UNKNOWN_ERROR;

    size_t key_len = RSA_size(rsa.get());
    int openssl_padding;
    switch (padding_) {
    case KM_PAD_NONE:
        if (data_.available_read() > key_len) return KM_ERROR_INVALID_INPUT_LENGTH;
        if (key_len != signature.available_read()) return KM_ERROR_VERIFICATION_FAILED;
        openssl_padding = RSA_NO_PADDING;
        break;
    case KM_PAD_RSA_PKCS1_1_5_SIGN:
        if (data_.available_read() + kPkcs1UndigestedSignaturePaddingOverhead > key_len) {
            LOG_E("Input too long: cannot verify %u-byte message with PKCS1 padding && %u-bit key",
                  data_.available_read(), key_len * 8);
            return KM_ERROR_INVALID_INPUT_LENGTH;
        }
        openssl_padding = RSA_PKCS1_PADDING;
        break;
    default:
        return KM_ERROR_UNSUPPORTED_PADDING_MODE;
    }

    UniquePtr<uint8_t[]> decrypted_data(new (std::nothrow) uint8_t[key_len]);
    if (!decrypted_data.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    int bytes_decrypted = RSA_public_decrypt(signature.available_read(), signature.peek_read(),
                                             decrypted_data.get(), rsa.get(), openssl_padding);
    if (bytes_decrypted < 0) return KM_ERROR_VERIFICATION_FAILED;

    const uint8_t* compare_pos = decrypted_data.get();
    size_t bytes_to_compare = bytes_decrypted;
    uint8_t zero_check_result = 0;
    if (padding_ == KM_PAD_NONE && data_.available_read() < bytes_to_compare) {
        // If the data is short, for "unpadded" signing we zero-pad to the left.  So during
        // verification we should have zeros on the left of the decrypted data.  Do a constant-time
        // check.
        const uint8_t* zero_end = compare_pos + bytes_to_compare - data_.available_read();
        while (compare_pos < zero_end)
            zero_check_result |= *compare_pos++;
        bytes_to_compare = data_.available_read();
    }
    if (memcmp_s(compare_pos, data_.peek_read(), bytes_to_compare) != 0 || zero_check_result != 0)
        return KM_ERROR_VERIFICATION_FAILED;
    return KM_ERROR_OK;
}

keymaster_error_t RsaVerifyOperation::VerifyDigested(const Buffer& signature) {
    if (!EVP_DigestVerifyFinal(&digest_ctx_, signature.peek_read(), signature.available_read()))
        return KM_ERROR_VERIFICATION_FAILED;
    return KM_ERROR_OK;
}

keymaster_error_t RsaCryptOperation::SetOaepDigestIfRequired(EVP_PKEY_CTX* pkey_ctx) {
    if (padding() != KM_PAD_RSA_OAEP) return KM_ERROR_OK;

    assert(digest_algorithm_ != nullptr);
    if (!EVP_PKEY_CTX_set_rsa_oaep_md(pkey_ctx, digest_algorithm_)) {
        return TranslateLastOpenSslError();
    }
    assert(mgf_digest_algorithm_ != nullptr);
    // MGF1 MD is always SHA1.
    if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf_digest_algorithm_)) {
        return TranslateLastOpenSslError();
    }
    return KM_ERROR_OK;
}

keymaster_error_t RsaCryptOperation::Begin(const AuthorizationSet& input_params,
                                           AuthorizationSet* output_params) {
    keymaster_error_t error = RsaOperation::Begin(input_params, output_params);
    if (error != KM_ERROR_OK) return error;
    return InitMgfDigest();
}

int RsaCryptOperation::GetOpensslPadding(keymaster_error_t* error) {
    *error = KM_ERROR_OK;
    switch (padding_) {
    case KM_PAD_NONE:
        return RSA_NO_PADDING;
    case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
        return RSA_PKCS1_PADDING;
    case KM_PAD_RSA_OAEP:
        return RSA_PKCS1_OAEP_PADDING;
    default:
        return -1;
    }
}

keymaster_error_t RsaCryptOperation::InitMgfDigest() {
    if (mgf_digest_ == KM_DIGEST_NONE) {
        return KM_ERROR_OK;
    }
    mgf_digest_algorithm_ = KmDigestToEvpDigest(mgf_digest_);
    if (mgf_digest_algorithm_ == nullptr) {
        return KM_ERROR_UNSUPPORTED_DIGEST;
    }
    return KM_ERROR_OK;
}

keymaster_error_t RsaEncryptOperation::Finish(const AuthorizationSet& additional_params,
                                              const Buffer& input, const Buffer& /* signature */,
                                              AuthorizationSet* /* output_params */,
                                              Buffer* output) {
    if (!output) return KM_ERROR_OUTPUT_PARAMETER_NULL;

    keymaster_error_t error = UpdateForFinish(additional_params, input);
    if (error != KM_ERROR_OK) return error;

    EVP_PKEY_CTX_Ptr ctx(EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
    if (!ctx.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;

    if (EVP_PKEY_encrypt_init(ctx.get()) <= 0) return TranslateLastOpenSslError();

    error = SetRsaPaddingInEvpContext(ctx.get(), false /* signing */);
    if (error != KM_ERROR_OK) return error;
    error = SetOaepDigestIfRequired(ctx.get());
    if (error != KM_ERROR_OK) return error;

    size_t outlen;
    if (EVP_PKEY_encrypt(ctx.get(), nullptr /* out */, &outlen, data_.peek_read(),
                         data_.available_read()) <= 0)
        return TranslateLastOpenSslError();

    if (!output->Reinitialize(outlen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;

    const uint8_t* to_encrypt = data_.peek_read();
    size_t to_encrypt_len = data_.available_read();
    UniquePtr<uint8_t[]> zero_padded;
    if (padding_ == KM_PAD_NONE && to_encrypt_len < outlen) {
        keymaster_error_t error = zero_pad_left(&zero_padded, outlen, data_);
        if (error != KM_ERROR_OK) return error;
        to_encrypt = zero_padded.get();
        to_encrypt_len = outlen;
    }

    if (EVP_PKEY_encrypt(ctx.get(), output->peek_write(), &outlen, to_encrypt, to_encrypt_len) <= 0)
        return TranslateLastOpenSslError();
    if (!output->advance_write(outlen)) return KM_ERROR_UNKNOWN_ERROR;

    return KM_ERROR_OK;
}

keymaster_error_t RsaDecryptOperation::Finish(const AuthorizationSet& additional_params,
                                              const Buffer& input, const Buffer& /* signature */,
                                              AuthorizationSet* /* output_params */,
                                              Buffer* output) {
    if (!output) return KM_ERROR_OUTPUT_PARAMETER_NULL;

    keymaster_error_t error = UpdateForFinish(additional_params, input);
    if (error != KM_ERROR_OK) return error;

    EVP_PKEY_CTX_Ptr ctx(EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
    if (!ctx.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;

    if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) return TranslateLastOpenSslError();

    error = SetRsaPaddingInEvpContext(ctx.get(), false /* signing */);
    if (error != KM_ERROR_OK) return error;
    error = SetOaepDigestIfRequired(ctx.get());
    if (error != KM_ERROR_OK) return error;

    size_t outlen;
    if (EVP_PKEY_decrypt(ctx.get(), nullptr /* out */, &outlen, data_.peek_read(),
                         data_.available_read()) <= 0)
        return TranslateLastOpenSslError();

    if (!output->Reinitialize(outlen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;

    const uint8_t* to_decrypt = data_.peek_read();
    size_t to_decrypt_len = data_.available_read();
    UniquePtr<uint8_t[]> zero_padded;
    if (padding_ == KM_PAD_NONE && to_decrypt_len < outlen) {
        keymaster_error_t error = zero_pad_left(&zero_padded, outlen, data_);
        if (error != KM_ERROR_OK) return error;
        to_decrypt = zero_padded.get();
        to_decrypt_len = outlen;
    }

    if (EVP_PKEY_decrypt(ctx.get(), output->peek_write(), &outlen, to_decrypt, to_decrypt_len) <= 0)
        return TranslateLastOpenSslError();
    if (!output->advance_write(outlen)) return KM_ERROR_UNKNOWN_ERROR;

    return KM_ERROR_OK;
}

}  // namespace keymaster
