/*
 * Copyright 2015 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 "nist_curve_key_exchange.h"

#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/err.h>
#include <openssl/evp.h>

#include "openssl_err.h"

namespace keymaster {

NistCurveKeyExchange::NistCurveKeyExchange(EC_KEY* private_key, keymaster_error_t* error)
    : private_key_(private_key) {
    if (!private_key_.get() || !EC_KEY_check_key(private_key_.get())) {
        *error = KM_ERROR_INVALID_ARGUMENT;
        return;
    }
    *error = ExtractPublicKey();
}

/* static */
NistCurveKeyExchange* NistCurveKeyExchange::GenerateKeyExchange(keymaster_ec_curve_t curve) {
    int curve_name;
    switch (curve) {
    case KM_EC_CURVE_P_224:
        curve_name = NID_secp224r1;
        break;
    case KM_EC_CURVE_P_256:
        curve_name = NID_X9_62_prime256v1;
        break;
    case KM_EC_CURVE_P_384:
        curve_name = NID_secp384r1;
        break;
    case KM_EC_CURVE_P_521:
        curve_name = NID_secp521r1;
        break;
    default:
        LOG_E("Not a NIST curve: %d", curve);
        return nullptr;
    }

    UniquePtr<EC_KEY, EC_KEY_Delete> key(EC_KEY_new_by_curve_name(curve_name));
    if (!key.get() || !EC_KEY_generate_key(key.get())) {
        return nullptr;
    }
    keymaster_error_t error;
    NistCurveKeyExchange* key_exchange = new NistCurveKeyExchange(key.release(), &error);
    if (error != KM_ERROR_OK) {
        delete key_exchange;
        return nullptr;
    }
    return key_exchange;
}

keymaster_error_t NistCurveKeyExchange::ExtractPublicKey() {
    const EC_GROUP* group = EC_KEY_get0_group(private_key_.get());
    size_t field_len_bits;
    keymaster_error_t error = ec_get_group_size(group, &field_len_bits);
    if (error != KM_ERROR_OK)
        return error;

    shared_secret_len_ = (field_len_bits + 7) / 8;
    public_key_len_ = 1 + 2 * shared_secret_len_;
    public_key_.reset(new uint8_t[public_key_len_]);
    if (EC_POINT_point2oct(group, EC_KEY_get0_public_key(private_key_.get()),
                           POINT_CONVERSION_UNCOMPRESSED, public_key_.get(), public_key_len_,
                           nullptr /* ctx */) != public_key_len_) {
        return TranslateLastOpenSslError();
    }
    return KM_ERROR_OK;
}

bool NistCurveKeyExchange::CalculateSharedKey(const Buffer& peer_public_value,
                                              Buffer* out_result) const {

    return CalculateSharedKey(peer_public_value.peek_read(), peer_public_value.available_read(),
                              out_result);
}

bool NistCurveKeyExchange::CalculateSharedKey(const uint8_t* peer_public_value,
                                              size_t peer_public_value_len,
                                              Buffer* out_result) const {
    const EC_GROUP* group = EC_KEY_get0_group(private_key_.get());
    UniquePtr<EC_POINT, EC_POINT_Delete> point(EC_POINT_new(group));
    if (!point.get() ||
        !EC_POINT_oct2point(/* also test if point is on curve */
                            group, point.get(), peer_public_value, peer_public_value_len,
                            nullptr /* ctx */) ||
        !EC_POINT_is_on_curve(group, point.get(), nullptr /* ctx */)) {
        LOG_E("Can't convert peer public value to point: %d", TranslateLastOpenSslError());
        return false;
    }

    UniquePtr<uint8_t[]> result(new uint8_t[shared_secret_len_]);
    if (ECDH_compute_key(result.get(), shared_secret_len_, point.get(), private_key_.get(),
                         nullptr /* kdf */) != static_cast<int>(shared_secret_len_)) {
        LOG_E("Can't compute ECDH shared key: %d", TranslateLastOpenSslError());
        return false;
    }

    out_result->Reinitialize(result.get(), shared_secret_len_);
    return true;
}

bool NistCurveKeyExchange::public_value(Buffer* public_value) const {
    if (public_key_.get() != nullptr && public_key_len_ != 0) {
        return public_value->Reinitialize(public_key_.get(), public_key_len_);
    }
    return false;
}

}  // namespace keymaster
