/*
 * 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.
 */

#ifndef SYSTEM_KEYMASTER_ECDSA_OPERATION_H_
#define SYSTEM_KEYMASTER_ECDSA_OPERATION_H_

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

#include <UniquePtr.h>

#include "operation.h"

namespace keymaster {

class EcdsaOperation : public Operation {
  public:
    EcdsaOperation(keymaster_purpose_t purpose, keymaster_digest_t digest, EVP_PKEY* key)
        : Operation(purpose), digest_(digest), ecdsa_key_(key) {
        EVP_MD_CTX_init(&digest_ctx_);
    }
    ~EcdsaOperation();

    keymaster_error_t Abort() override { return KM_ERROR_OK; }

  protected:
    keymaster_error_t StoreData(const Buffer& input, size_t* input_consumed);
    keymaster_error_t InitDigest();

    keymaster_digest_t digest_;
    const EVP_MD* digest_algorithm_;
    EVP_PKEY* ecdsa_key_;
    EVP_MD_CTX digest_ctx_;
    Buffer data_;
};

class EcdsaSignOperation : public EcdsaOperation {
  public:
    EcdsaSignOperation(keymaster_digest_t digest, EVP_PKEY* key)
        : EcdsaOperation(KM_PURPOSE_SIGN, digest, key) {}
    keymaster_error_t Begin(const AuthorizationSet& input_params,
                            AuthorizationSet* output_params) override;
    keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input,
                             AuthorizationSet* output_params, Buffer* output,
                             size_t* input_consumed) override;
    keymaster_error_t Finish(const AuthorizationSet& additional_params, const Buffer& signature,
                             AuthorizationSet* output_params, Buffer* output) override;
};

class EcdsaVerifyOperation : public EcdsaOperation {
  public:
    EcdsaVerifyOperation(keymaster_digest_t digest, EVP_PKEY* key)
        : EcdsaOperation(KM_PURPOSE_VERIFY, digest, key) {}
    keymaster_error_t Begin(const AuthorizationSet& input_params,
                            AuthorizationSet* output_params) override;
    keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input,
                             AuthorizationSet* output_params, Buffer* output,
                             size_t* input_consumed) override;
    keymaster_error_t Finish(const AuthorizationSet& additional_params, const Buffer& signature,
                             AuthorizationSet* output_params, Buffer* output) override;
};

class EcdsaOperationFactory : public OperationFactory {
  private:
    KeyType registry_key() const override { return KeyType(KM_ALGORITHM_EC, purpose()); }
    Operation* CreateOperation(const Key& key, const AuthorizationSet& begin_params,
                               keymaster_error_t* error) override;
    const keymaster_digest_t* SupportedDigests(size_t* digest_count) const override;

    virtual keymaster_purpose_t purpose() const = 0;
    virtual Operation* InstantiateOperation(keymaster_digest_t digest, EVP_PKEY* key) = 0;
};

class EcdsaSignOperationFactory : public EcdsaOperationFactory {
  private:
    keymaster_purpose_t purpose() const override { return KM_PURPOSE_SIGN; }
    Operation* InstantiateOperation(keymaster_digest_t digest, EVP_PKEY* key) {
        return new (std::nothrow) EcdsaSignOperation(digest, key);
    }
};

class EcdsaVerifyOperationFactory : public EcdsaOperationFactory {
  public:
    keymaster_purpose_t purpose() const override { return KM_PURPOSE_VERIFY; }
    Operation* InstantiateOperation(keymaster_digest_t digest, EVP_PKEY* key) {
        return new (std::nothrow) EcdsaVerifyOperation(digest, key);
    }
};

}  // namespace keymaster

#endif  // SYSTEM_KEYMASTER_ECDSA_OPERATION_H_
