/*
 * 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 "aes_operation.h"

#include <stdio.h>

#include <new>

#include <UniquePtr.h>

#include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/rand.h>

#include <keymaster/logger.h>

#include "aes_key.h"
#include "openssl_err.h"

namespace keymaster {

static const size_t GCM_NONCE_SIZE = 12;
static const size_t GCM_MAX_TAG_LENGTH = 16;
static const size_t GCM_MIN_TAG_LENGTH = 12;

inline bool allows_padding(keymaster_block_mode_t block_mode) {
    switch (block_mode) {
    case KM_MODE_CTR:
    case KM_MODE_GCM:
        return false;
    case KM_MODE_ECB:
    case KM_MODE_CBC:
        return true;
    }
    assert(false /* Can't get here */);
    return false;
}

static keymaster_error_t GetAndValidateGcmTagLength(const AuthorizationSet& begin_params,
                                                    const AuthorizationSet& key_params,
                                                    size_t* tag_length) {
    uint32_t tag_length_bits;
    if (!begin_params.GetTagValue(TAG_MAC_LENGTH, &tag_length_bits)) {
        return KM_ERROR_MISSING_MAC_LENGTH;
    }

    uint32_t min_tag_length_bits;
    if (!key_params.GetTagValue(TAG_MIN_MAC_LENGTH, &min_tag_length_bits)) {
        LOG_E("AES GCM key must have KM_TAG_MIN_MAC_LENGTH", 0);
        return KM_ERROR_INVALID_KEY_BLOB;
    }

    if (tag_length_bits % 8 != 0 || tag_length_bits > kMaxGcmTagLength ||
        tag_length_bits < kMinGcmTagLength) {
        return KM_ERROR_UNSUPPORTED_MAC_LENGTH;
    }

    if (tag_length_bits < min_tag_length_bits) {
        return KM_ERROR_INVALID_MAC_LENGTH;
    }

    *tag_length = tag_length_bits / 8;
    return KM_ERROR_OK;
}

Operation* AesOperationFactory::CreateOperation(const Key& key,
                                                const AuthorizationSet& begin_params,
                                                keymaster_error_t* error) {
    *error = KM_ERROR_OK;
    const SymmetricKey* symmetric_key = static_cast<const SymmetricKey*>(&key);

    switch (symmetric_key->key_data_size()) {
    case 16:
    case 24:
    case 32:
        break;
    default:
        *error = KM_ERROR_UNSUPPORTED_KEY_SIZE;
        return nullptr;
    }

    keymaster_block_mode_t block_mode;
    if (!begin_params.GetTagValue(TAG_BLOCK_MODE, &block_mode)) {
        LOG_E("%d block modes specified in begin params", begin_params.GetTagCount(TAG_BLOCK_MODE));
        *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
        return nullptr;
    } else if (!supported(block_mode)) {
        LOG_E("Block mode %d not supported", block_mode);
        *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
        return nullptr;
    } else if (!key.authorizations().Contains(TAG_BLOCK_MODE, block_mode)) {
        LOG_E("Block mode %d was specified, but not authorized by key", block_mode);
        *error = KM_ERROR_INCOMPATIBLE_BLOCK_MODE;
        return nullptr;
    }

    size_t tag_length = 0;
    if (block_mode == KM_MODE_GCM) {
        *error = GetAndValidateGcmTagLength(begin_params, key.authorizations(), &tag_length);
        if (*error != KM_ERROR_OK) {
            return nullptr;
        }
    }

    keymaster_padding_t padding;
    if (!GetAndValidatePadding(begin_params, key, &padding, error)) {
        return nullptr;
    }
    if (!allows_padding(block_mode) && padding != KM_PAD_NONE) {
        LOG_E("Mode does not support padding", 0);
        *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
        return nullptr;
    }

    bool caller_nonce = key.authorizations().GetTagValue(TAG_CALLER_NONCE);

    Operation* op = nullptr;
    switch (purpose()) {
    case KM_PURPOSE_ENCRYPT:
        op = new (std::nothrow)
            AesEvpEncryptOperation(block_mode, padding, caller_nonce, tag_length,
                                   symmetric_key->key_data(), symmetric_key->key_data_size());
        break;
    case KM_PURPOSE_DECRYPT:
        op = new (std::nothrow)
            AesEvpDecryptOperation(block_mode, padding, tag_length, symmetric_key->key_data(),
                                   symmetric_key->key_data_size());
        break;
    default:
        *error = KM_ERROR_UNSUPPORTED_PURPOSE;
        return nullptr;
    }

    if (!op)
        *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
    return op;
}

static const keymaster_block_mode_t supported_block_modes[] = {KM_MODE_ECB, KM_MODE_CBC,
                                                               KM_MODE_CTR, KM_MODE_GCM};

const keymaster_block_mode_t*
AesOperationFactory::SupportedBlockModes(size_t* block_mode_count) const {
    *block_mode_count = array_length(supported_block_modes);
    return supported_block_modes;
}

static const keymaster_padding_t supported_padding_modes[] = {KM_PAD_NONE, KM_PAD_PKCS7};
const keymaster_padding_t*
AesOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
    *padding_mode_count = array_length(supported_padding_modes);
    return supported_padding_modes;
}

AesEvpOperation::AesEvpOperation(keymaster_purpose_t purpose, keymaster_block_mode_t block_mode,
                                 keymaster_padding_t padding, bool caller_iv, size_t tag_length,
                                 const uint8_t* key, size_t key_size)
    : Operation(purpose), block_mode_(block_mode), caller_iv_(caller_iv), tag_length_(tag_length),
      data_started_(false), key_size_(key_size), padding_(padding) {
    memcpy(key_, key, key_size_);
    EVP_CIPHER_CTX_init(&ctx_);
}

AesEvpOperation::~AesEvpOperation() {
    EVP_CIPHER_CTX_cleanup(&ctx_);
    memset_s(aad_block_buf_.get(), AES_BLOCK_SIZE, 0);
}

keymaster_error_t AesEvpOperation::Begin(const AuthorizationSet& /* input_params */,
                                         AuthorizationSet* /* output_params */) {
    if (block_mode_ == KM_MODE_GCM) {
        aad_block_buf_length_ = 0;
        aad_block_buf_.reset(new (std::nothrow) uint8_t[AES_BLOCK_SIZE]);
        if (!aad_block_buf_.get())
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }

    return InitializeCipher();
}

keymaster_error_t AesEvpOperation::Update(const AuthorizationSet& additional_params,
                                          const Buffer& input,
                                          AuthorizationSet* /* output_params */, Buffer* output,
                                          size_t* input_consumed) {
    keymaster_error_t error;
    if (block_mode_ == KM_MODE_GCM)
        if (!HandleAad(additional_params, input, &error))
            return error;

    if (!InternalUpdate(input.peek_read(), input.available_read(), output, &error))
        return error;
    *input_consumed = input.available_read();

    return KM_ERROR_OK;
}

inline bool is_bad_decrypt(unsigned long error) {
    return (ERR_GET_LIB(error) == ERR_LIB_CIPHER &&  //
            ERR_GET_REASON(error) == CIPHER_R_BAD_DECRYPT);
}

keymaster_error_t AesEvpOperation::Finish(const AuthorizationSet& /* additional_params */,
                                          const Buffer& /* signature */,
                                          AuthorizationSet* /* output_params */, Buffer* output) {
    if (!output->reserve(AES_BLOCK_SIZE))
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;

    keymaster_error_t error;
    if (block_mode_ == KM_MODE_GCM && aad_block_buf_length_ > 0 &&
        !ProcessBufferedAadBlock(&error)) {
        return error;
    }

    int output_written = -1;
    if (!EVP_CipherFinal_ex(&ctx_, output->peek_write(), &output_written)) {
        if (tag_length_ > 0)
            return KM_ERROR_VERIFICATION_FAILED;
        LOG_E("Error encrypting final block: %s", ERR_error_string(ERR_peek_last_error(), NULL));
        return TranslateLastOpenSslError();
    }

    assert(output_written <= AES_BLOCK_SIZE);
    if (!output->advance_write(output_written))
        return KM_ERROR_UNKNOWN_ERROR;
    return KM_ERROR_OK;
}

bool AesEvpOperation::need_iv() const {
    switch (block_mode_) {
    case KM_MODE_CBC:
    case KM_MODE_CTR:
    case KM_MODE_GCM:
        return true;
    case KM_MODE_ECB:
        return false;
    default:
        // Shouldn't get here.
        assert(false);
        return false;
    }
}

keymaster_error_t AesEvpOperation::InitializeCipher() {
    const EVP_CIPHER* cipher;
    switch (block_mode_) {
    case KM_MODE_ECB:
        switch (key_size_) {
        case 16:
            cipher = EVP_aes_128_ecb();
            break;
        case 24:
            cipher = EVP_aes_192_ecb();
            break;
        case 32:
            cipher = EVP_aes_256_ecb();
            break;
        default:
            return KM_ERROR_UNSUPPORTED_KEY_SIZE;
        }
        break;
    case KM_MODE_CBC:
        switch (key_size_) {
        case 16:
            cipher = EVP_aes_128_cbc();
            break;
        case 24:
            cipher = EVP_aes_192_cbc();
            break;
        case 32:
            cipher = EVP_aes_256_cbc();
            break;
        default:
            return KM_ERROR_UNSUPPORTED_KEY_SIZE;
        }
        break;
    case KM_MODE_CTR:
        switch (key_size_) {
        case 16:
            cipher = EVP_aes_128_ctr();
            break;
        case 24:
            cipher = EVP_aes_192_ctr();
            break;
        case 32:
            cipher = EVP_aes_256_ctr();
            break;
        default:
            return KM_ERROR_UNSUPPORTED_KEY_SIZE;
        }
        break;
    case KM_MODE_GCM:
        switch (key_size_) {
        case 16:
            cipher = EVP_aes_128_gcm();
            break;
        case 24:
            cipher = EVP_aes_192_gcm();
            break;
        case 32:
            cipher = EVP_aes_256_gcm();
            break;
        default:
            return KM_ERROR_UNSUPPORTED_KEY_SIZE;
        }
        break;
    default:
        return KM_ERROR_UNSUPPORTED_BLOCK_MODE;
    }

    if (!EVP_CipherInit_ex(&ctx_, cipher, NULL /* engine */, key_, iv_.get(), evp_encrypt_mode()))
        return TranslateLastOpenSslError();

    switch (padding_) {
    case KM_PAD_NONE:
        EVP_CIPHER_CTX_set_padding(&ctx_, 0 /* disable padding */);
        break;
    case KM_PAD_PKCS7:
        // This is the default for OpenSSL EVP cipher operations.
        break;
    default:
        return KM_ERROR_UNSUPPORTED_PADDING_MODE;
    }

    if (block_mode_ == KM_MODE_GCM) {
        aad_block_buf_length_ = 0;
        aad_block_buf_.reset(new (std::nothrow) uint8_t[AES_BLOCK_SIZE]);
        if (!aad_block_buf_.get())
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }

    return KM_ERROR_OK;
}

keymaster_error_t AesEvpOperation::GetIv(const AuthorizationSet& input_params) {
    keymaster_blob_t iv_blob;
    if (!input_params.GetTagValue(TAG_NONCE, &iv_blob)) {
        LOG_E("No IV provided", 0);
        return KM_ERROR_INVALID_ARGUMENT;
    }
    if (block_mode_ != KM_MODE_GCM && iv_blob.data_length != AES_BLOCK_SIZE) {
        LOG_E("Expected %d-byte IV for AES operation, but got %d bytes", AES_BLOCK_SIZE,
              iv_blob.data_length);
        return KM_ERROR_INVALID_NONCE;
    }
    if (block_mode_ == KM_MODE_GCM && iv_blob.data_length != GCM_NONCE_SIZE) {
        LOG_E("Expected %d-byte nonce for AES-GCM operation, but got %d bytes", GCM_NONCE_SIZE,
              iv_blob.data_length);
        return KM_ERROR_INVALID_NONCE;
    }
    iv_.reset(dup_array(iv_blob.data, iv_blob.data_length));
    if (!iv_.get())
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    iv_length_ = iv_blob.data_length;
    return KM_ERROR_OK;
}

/*
 * Process Incoming Associated Authentication Data.
 *
 * This method is more complex than might be expected, because the underlying library silently does
 * the wrong thing when given partial AAD blocks, so we have to take care to process AAD in
 * AES_BLOCK_SIZE increments, buffering (in aad_block_buf_) when given smaller amounts of data.
 */
bool AesEvpOperation::HandleAad(const AuthorizationSet& input_params, const Buffer& input,
                                keymaster_error_t* error) {
    assert(tag_length_ > 0);
    assert(error);

    keymaster_blob_t aad;
    if (input_params.GetTagValue(TAG_ASSOCIATED_DATA, &aad)) {
        if (data_started_) {
            *error = KM_ERROR_INVALID_TAG;
            return false;
        }

        if (aad_block_buf_length_ > 0) {
            FillBufferedAadBlock(&aad);
            if (aad_block_buf_length_ == AES_BLOCK_SIZE && !ProcessBufferedAadBlock(error))
                return false;
        }

        size_t blocks_to_process = aad.data_length / AES_BLOCK_SIZE;
        if (blocks_to_process && !ProcessAadBlocks(aad.data, blocks_to_process, error))
            return false;
        aad.data += blocks_to_process * AES_BLOCK_SIZE;
        aad.data_length -= blocks_to_process * AES_BLOCK_SIZE;

        FillBufferedAadBlock(&aad);
        assert(aad.data_length == 0);
    }

    if (input.available_read()) {
        data_started_ = true;
        // Data has begun, no more AAD is allowed.  Process any buffered AAD.
        if (aad_block_buf_length_ > 0 && !ProcessBufferedAadBlock(error))
            return false;
    }

    return true;
}

bool AesEvpOperation::ProcessBufferedAadBlock(keymaster_error_t* error) {
    int output_written;
    if (EVP_CipherUpdate(&ctx_, nullptr /* out */, &output_written, aad_block_buf_.get(),
                         aad_block_buf_length_)) {
        aad_block_buf_length_ = 0;
        return true;
    }
    *error = TranslateLastOpenSslError();
    return false;
}

bool AesEvpOperation::ProcessAadBlocks(const uint8_t* data, size_t blocks,
                                       keymaster_error_t* error) {
    int output_written;
    if (EVP_CipherUpdate(&ctx_, nullptr /* out */, &output_written, data, blocks * AES_BLOCK_SIZE))
        return true;
    *error = TranslateLastOpenSslError();
    return false;
}

inline size_t min(size_t a, size_t b) {
    return (a < b) ? a : b;
}

void AesEvpOperation::FillBufferedAadBlock(keymaster_blob_t* aad) {
    size_t to_buffer = min(AES_BLOCK_SIZE - aad_block_buf_length_, aad->data_length);
    memcpy(aad_block_buf_.get() + aad_block_buf_length_, aad->data, to_buffer);
    aad->data += to_buffer;
    aad->data_length -= to_buffer;
    aad_block_buf_length_ += to_buffer;
}

bool AesEvpOperation::InternalUpdate(const uint8_t* input, size_t input_length, Buffer* output,
                                     keymaster_error_t* error) {
    assert(output);
    assert(error);

    if (!input_length)
        return true;

    if (!output->reserve(input_length + AES_BLOCK_SIZE)) {
        *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
        return false;
    }

    int output_written = -1;
    if (!EVP_CipherUpdate(&ctx_, output->peek_write(), &output_written, input, input_length)) {
        *error = TranslateLastOpenSslError();
        return false;
    }
    return output->advance_write(output_written);
}

keymaster_error_t AesEvpEncryptOperation::Begin(const AuthorizationSet& input_params,
                                                AuthorizationSet* output_params) {
    if (!output_params)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    if (need_iv()) {
        keymaster_error_t error = KM_ERROR_OK;
        if (input_params.find(TAG_NONCE) == -1)
            error = GenerateIv();
        else if (caller_iv_)
            error = GetIv(input_params);
        else
            error = KM_ERROR_CALLER_NONCE_PROHIBITED;

        if (error == KM_ERROR_OK)
            output_params->push_back(TAG_NONCE, iv_.get(), iv_length_);
        else
            return error;
    }

    return AesEvpOperation::Begin(input_params, output_params);
}

keymaster_error_t AesEvpEncryptOperation::Finish(const AuthorizationSet& additional_params,
                                                 const Buffer& signature,
                                                 AuthorizationSet* output_params, Buffer* output) {
    if (!output->reserve(AES_BLOCK_SIZE + tag_length_))
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;

    keymaster_error_t error =
        AesEvpOperation::Finish(additional_params, signature, output_params, output);
    if (error != KM_ERROR_OK)
        return error;

    if (tag_length_ > 0) {
        if (!output->reserve(output->available_read() + tag_length_))
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;

        if (!EVP_CIPHER_CTX_ctrl(&ctx_, EVP_CTRL_GCM_GET_TAG, tag_length_, output->peek_write()))
            return TranslateLastOpenSslError();
        if (!output->advance_write(tag_length_))
            return KM_ERROR_UNKNOWN_ERROR;
    }

    return KM_ERROR_OK;
}

keymaster_error_t AesEvpEncryptOperation::GenerateIv() {
    iv_length_ = (block_mode_ == KM_MODE_GCM) ? GCM_NONCE_SIZE : AES_BLOCK_SIZE;
    iv_.reset(new (std::nothrow) uint8_t[iv_length_]);
    if (!iv_.get())
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    if (RAND_bytes(iv_.get(), iv_length_) != 1)
        return TranslateLastOpenSslError();
    return KM_ERROR_OK;
}

keymaster_error_t AesEvpDecryptOperation::Begin(const AuthorizationSet& input_params,
                                                AuthorizationSet* output_params) {
    if (need_iv()) {
        keymaster_error_t error = GetIv(input_params);
        if (error != KM_ERROR_OK)
            return error;
    }

    if (tag_length_ > 0) {
        tag_buf_length_ = 0;
        tag_buf_.reset(new (std::nothrow) uint8_t[tag_length_]);
        if (!tag_buf_.get())
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }

    return AesEvpOperation::Begin(input_params, output_params);
}

keymaster_error_t AesEvpDecryptOperation::Update(const AuthorizationSet& additional_params,
                                                 const Buffer& input,
                                                 AuthorizationSet* /* output_params */,
                                                 Buffer* output, size_t* input_consumed) {
    if (!output || !input_consumed)
        return KM_ERROR_OUTPUT_PARAMETER_NULL;

    // Barring error, we'll consume it all.
    *input_consumed = input.available_read();

    keymaster_error_t error;
    if (block_mode_ == KM_MODE_GCM) {
        if (!HandleAad(additional_params, input, &error))
            return error;
        return ProcessAllButTagLengthBytes(input, output);
    }

    if (!InternalUpdate(input.peek_read(), input.available_read(), output, &error))
        return error;
    return KM_ERROR_OK;
}

keymaster_error_t AesEvpDecryptOperation::ProcessAllButTagLengthBytes(const Buffer& input,
                                                                      Buffer* output) {
    if (input.available_read() <= tag_buf_unused()) {
        BufferCandidateTagData(input.peek_read(), input.available_read());
        return KM_ERROR_OK;
    }

    const size_t data_available = tag_buf_length_ + input.available_read();

    const size_t to_process = data_available - tag_length_;
    const size_t to_process_from_tag_buf = min(to_process, tag_buf_length_);
    const size_t to_process_from_input = to_process - to_process_from_tag_buf;

    if (!output->reserve(to_process + AES_BLOCK_SIZE))
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;

    keymaster_error_t error;
    if (!ProcessTagBufContentsAsData(to_process_from_tag_buf, output, &error))
        return error;

    if (!InternalUpdate(input.peek_read(), to_process_from_input, output, &error))
        return error;

    BufferCandidateTagData(input.peek_read() + to_process_from_input,
                           input.available_read() - to_process_from_input);
    assert(tag_buf_unused() == 0);

    return KM_ERROR_OK;
}

bool AesEvpDecryptOperation::ProcessTagBufContentsAsData(size_t to_process, Buffer* output,
                                                         keymaster_error_t* error) {
    assert(to_process <= tag_buf_length_);
    if (!InternalUpdate(tag_buf_.get(), to_process, output, error))
        return false;
    if (to_process < tag_buf_length_)
        memmove(tag_buf_.get(), tag_buf_.get() + to_process, tag_buf_length_ - to_process);
    tag_buf_length_ -= to_process;
    return true;
}

void AesEvpDecryptOperation::BufferCandidateTagData(const uint8_t* data, size_t data_length) {
    assert(data_length <= tag_length_ - tag_buf_length_);
    memcpy(tag_buf_.get() + tag_buf_length_, data, data_length);
    tag_buf_length_ += data_length;
}

keymaster_error_t AesEvpDecryptOperation::Finish(const AuthorizationSet& additional_params,
                                                 const Buffer& signature,
                                                 AuthorizationSet* output_params, Buffer* output) {
    if (tag_buf_length_ < tag_length_)
        return KM_ERROR_INVALID_INPUT_LENGTH;
    else if (tag_length_ > 0 &&
             !EVP_CIPHER_CTX_ctrl(&ctx_, EVP_CTRL_GCM_SET_TAG, tag_length_, tag_buf_.get()))
        return TranslateLastOpenSslError();

    return AesEvpOperation::Finish(additional_params, signature, output_params, output);
}

keymaster_error_t AesEvpOperation::Abort() {
    return KM_ERROR_OK;
}

}  // namespace keymaster
