/*
 * Copyright (C) 2020 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/cppcose/cppcose.h>

#include <iostream>
#include <stdio.h>

#include <cppbor.h>
#include <cppbor_parse.h>
#include <openssl/ecdsa.h>

#include <openssl/err.h>

namespace cppcose {
constexpr int kP256AffinePointSize = 32;

using EVP_PKEY_Ptr = bssl::UniquePtr<EVP_PKEY>;
using EVP_PKEY_CTX_Ptr = bssl::UniquePtr<EVP_PKEY_CTX>;
using ECDSA_SIG_Ptr = bssl::UniquePtr<ECDSA_SIG>;
using EC_KEY_Ptr = bssl::UniquePtr<EC_KEY>;

namespace {

ErrMsgOr<bssl::UniquePtr<EVP_CIPHER_CTX>> aesGcmInitAndProcessAad(const bytevec& key,
                                                                  const bytevec& nonce,
                                                                  const bytevec& aad,
                                                                  bool encrypt) {
    if (key.size() != kAesGcmKeySize) return "Invalid key size";

    bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
    if (!ctx) return "Failed to allocate cipher context";

    if (!EVP_CipherInit_ex(ctx.get(), EVP_aes_256_gcm(), nullptr /* engine */, key.data(),
                           nonce.data(), encrypt ? 1 : 0)) {
        return "Failed to initialize cipher";
    }

    int outlen;
    if (!aad.empty() && !EVP_CipherUpdate(ctx.get(), nullptr /* out; null means AAD */, &outlen,
                                          aad.data(), aad.size())) {
        return "Failed to process AAD";
    }

    return std::move(ctx);
}

ErrMsgOr<bytevec> signEcdsaDigest(const bytevec& key, const bytevec& data) {
    auto bn = BIGNUM_Ptr(BN_bin2bn(key.data(), key.size(), nullptr));
    if (bn.get() == nullptr) {
        return "Error creating BIGNUM";
    }

    auto ec_key = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
    if (EC_KEY_set_private_key(ec_key.get(), bn.get()) != 1) {
        return "Error setting private key from BIGNUM";
    }

    auto sig = ECDSA_SIG_Ptr(ECDSA_do_sign(data.data(), data.size(), ec_key.get()));
    if (sig == nullptr) {
        return "Error signing digest";
    }
    size_t len = i2d_ECDSA_SIG(sig.get(), nullptr);
    bytevec signature(len);
    unsigned char* p = (unsigned char*)signature.data();
    i2d_ECDSA_SIG(sig.get(), &p);
    return signature;
}

ErrMsgOr<bytevec> ecdh(const bytevec& publicKey, const bytevec& privateKey) {
    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
    auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
    if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
        1) {
        return "Error decoding publicKey";
    }
    auto ecKey = EC_KEY_Ptr(EC_KEY_new());
    auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
    if (ecKey.get() == nullptr || pkey.get() == nullptr) {
        return "Memory allocation failed";
    }
    if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
        return "Error setting group";
    }
    if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
        return "Error setting point";
    }
    if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
        return "Error setting key";
    }

    auto bn = BIGNUM_Ptr(BN_bin2bn(privateKey.data(), privateKey.size(), nullptr));
    if (bn.get() == nullptr) {
        return "Error creating BIGNUM for private key";
    }
    auto privEcKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
    if (EC_KEY_set_private_key(privEcKey.get(), bn.get()) != 1) {
        return "Error setting private key from BIGNUM";
    }
    auto privPkey = EVP_PKEY_Ptr(EVP_PKEY_new());
    if (EVP_PKEY_set1_EC_KEY(privPkey.get(), privEcKey.get()) != 1) {
        return "Error setting private key";
    }

    auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(privPkey.get(), NULL));
    if (ctx.get() == nullptr) {
        return "Error creating context";
    }

    if (EVP_PKEY_derive_init(ctx.get()) != 1) {
        return "Error initializing context";
    }

    if (EVP_PKEY_derive_set_peer(ctx.get(), pkey.get()) != 1) {
        return "Error setting peer";
    }

    /* Determine buffer length for shared secret */
    size_t secretLen = 0;
    if (EVP_PKEY_derive(ctx.get(), NULL, &secretLen) != 1) {
        return "Error determing length of shared secret";
    }
    bytevec sharedSecret(secretLen);

    if (EVP_PKEY_derive(ctx.get(), sharedSecret.data(), &secretLen) != 1) {
        return "Error deriving shared secret";
    }
    return sharedSecret;
}

}  // namespace

ErrMsgOr<bytevec> ecdsaCoseSignatureToDer(const bytevec& ecdsaCoseSignature) {
    if (ecdsaCoseSignature.size() != 64) {
        return "COSE signature wrong length";
    }

    auto rBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data(), 32, nullptr));
    if (rBn.get() == nullptr) {
        return "Error creating BIGNUM for r";
    }

    auto sBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data() + 32, 32, nullptr));
    if (sBn.get() == nullptr) {
        return "Error creating BIGNUM for s";
    }

    ECDSA_SIG sig;
    sig.r = rBn.get();
    sig.s = sBn.get();

    size_t len = i2d_ECDSA_SIG(&sig, nullptr);
    bytevec derSignature(len);
    unsigned char* p = (unsigned char*)derSignature.data();
    i2d_ECDSA_SIG(&sig, &p);
    return derSignature;
}

ErrMsgOr<bytevec> ecdsaDerSignatureToCose(const bytevec& ecdsaSignature) {
    const unsigned char* p = ecdsaSignature.data();
    auto sig = ECDSA_SIG_Ptr(d2i_ECDSA_SIG(nullptr, &p, ecdsaSignature.size()));
    if (sig == nullptr) {
        return "Error decoding DER signature";
    }

    bytevec ecdsaCoseSignature(64, 0);
    if (BN_bn2binpad(ECDSA_SIG_get0_r(sig.get()), ecdsaCoseSignature.data(), 32) != 32) {
        return "Error encoding r";
    }
    if (BN_bn2binpad(ECDSA_SIG_get0_s(sig.get()), ecdsaCoseSignature.data() + 32, 32) != 32) {
        return "Error encoding s";
    }
    return ecdsaCoseSignature;
}

ErrMsgOr<HmacSha256> generateHmacSha256(const bytevec& key, const bytevec& data) {
    HmacSha256 digest;
    unsigned int outLen;
    uint8_t* out = HMAC(EVP_sha256(),              //
                        key.data(), key.size(),    //
                        data.data(), data.size(),  //
                        digest.data(), &outLen);

    if (out == nullptr || outLen != digest.size()) {
        return "Error generating HMAC";
    }
    return digest;
}

ErrMsgOr<HmacSha256> generateCoseMac0Mac(HmacSha256Function macFunction, const bytevec& externalAad,
                                         const bytevec& payload) {
    auto macStructure = cppbor::Array()
                            .add("MAC0")
                            .add(cppbor::Map().add(ALGORITHM, HMAC_256).canonicalize().encode())
                            .add(externalAad)
                            .add(payload)
                            .encode();

    auto macTag = macFunction(macStructure);
    if (!macTag) {
        return "Error computing public key MAC";
    }

    return *macTag;
}

ErrMsgOr<cppbor::Array> constructCoseMac0(HmacSha256Function macFunction,
                                          const bytevec& externalAad, const bytevec& payload) {
    auto tag = generateCoseMac0Mac(macFunction, externalAad, payload);
    if (!tag) return tag.moveMessage();

    return cppbor::Array()
        .add(cppbor::Map().add(ALGORITHM, HMAC_256).canonicalize().encode())
        .add(cppbor::Map() /* unprotected */)
        .add(payload)
        .add(std::pair(tag->begin(), tag->end()));
}

ErrMsgOr<bytevec /* payload */> verifyAndParseCoseMac0(const cppbor::Item* macItem,
                                                       const bytevec& macKey) {
    auto mac = macItem ? macItem->asArray() : nullptr;
    if (!mac || mac->size() != kCoseMac0EntryCount) {
        return "Invalid COSE_Mac0";
    }

    auto protectedParms = mac->get(kCoseMac0ProtectedParams)->asBstr();
    auto unprotectedParms = mac->get(kCoseMac0UnprotectedParams)->asMap();
    auto payload = mac->get(kCoseMac0Payload)->asBstr();
    auto tag = mac->get(kCoseMac0Tag)->asBstr();
    if (!protectedParms || !unprotectedParms || !payload || !tag) {
        return "Invalid COSE_Mac0 contents";
    }

    auto [protectedMap, _, errMsg] = cppbor::parse(protectedParms);
    if (!protectedMap || !protectedMap->asMap()) {
        return "Invalid Mac0 protected: " + errMsg;
    }
    auto& algo = protectedMap->asMap()->get(ALGORITHM);
    if (!algo || !algo->asInt() || algo->asInt()->value() != HMAC_256) {
        return "Unsupported Mac0 algorithm";
    }

    auto macFunction = [&macKey](const bytevec& input) {
        return generateHmacSha256(macKey, input);
    };
    auto macTag = generateCoseMac0Mac(macFunction, {} /* external_aad */, payload->value());
    if (!macTag) return macTag.moveMessage();

    if (macTag->size() != tag->value().size() ||
        CRYPTO_memcmp(macTag->data(), tag->value().data(), macTag->size()) != 0) {
        return "MAC tag mismatch";
    }

    return payload->value();
}

ErrMsgOr<bytevec> createECDSACoseSign1Signature(const bytevec& key, const bytevec& protectedParams,
                                                const bytevec& payload, const bytevec& aad) {
    bytevec signatureInput = cppbor::Array()
                                 .add("Signature1")  //
                                 .add(protectedParams)
                                 .add(aad)
                                 .add(payload)
                                 .encode();
    auto ecdsaSignature = signEcdsaDigest(key, sha256(signatureInput));
    if (!ecdsaSignature) return ecdsaSignature.moveMessage();

    return ecdsaDerSignatureToCose(*ecdsaSignature);
}

ErrMsgOr<bytevec> createCoseSign1Signature(const bytevec& key, const bytevec& protectedParams,
                                           const bytevec& payload, const bytevec& aad) {
    bytevec signatureInput = cppbor::Array()
                                 .add("Signature1")  //
                                 .add(protectedParams)
                                 .add(aad)
                                 .add(payload)
                                 .encode();

    if (key.size() != ED25519_PRIVATE_KEY_LEN) return "Invalid signing key";
    bytevec signature(ED25519_SIGNATURE_LEN);
    if (!ED25519_sign(signature.data(), signatureInput.data(), signatureInput.size(), key.data())) {
        return "Signing failed";
    }

    return signature;
}

ErrMsgOr<cppbor::Array> constructECDSACoseSign1(const bytevec& key, cppbor::Map protectedParams,
                                                const bytevec& payload, const bytevec& aad) {
    bytevec protParms = protectedParams.add(ALGORITHM, ES256).canonicalize().encode();
    auto signature = createECDSACoseSign1Signature(key, protParms, payload, aad);
    if (!signature) return signature.moveMessage();

    return cppbor::Array()
        .add(std::move(protParms))
        .add(cppbor::Map() /* unprotected parameters */)
        .add(std::move(payload))
        .add(std::move(*signature));
}

ErrMsgOr<cppbor::Array> constructCoseSign1(const bytevec& key, cppbor::Map protectedParams,
                                           const bytevec& payload, const bytevec& aad) {
    bytevec protParms = protectedParams.add(ALGORITHM, EDDSA).canonicalize().encode();
    auto signature = createCoseSign1Signature(key, protParms, payload, aad);
    if (!signature) return signature.moveMessage();

    return cppbor::Array()
        .add(std::move(protParms))
        .add(cppbor::Map() /* unprotected parameters */)
        .add(std::move(payload))
        .add(std::move(*signature));
}

ErrMsgOr<cppbor::Array> constructCoseSign1(const bytevec& key, const bytevec& payload,
                                           const bytevec& aad) {
    return constructCoseSign1(key, {} /* protectedParams */, payload, aad);
}

ErrMsgOr<bytevec> verifyAndParseCoseSign1(const cppbor::Array* coseSign1,
                                          const bytevec& signingCoseKey, const bytevec& aad) {
    if (!coseSign1 || coseSign1->size() != kCoseSign1EntryCount) {
        return "Invalid COSE_Sign1";
    }

    const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
    const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
    const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();

    if (!protectedParams || !unprotectedParams || !payload) {
        return "Missing input parameters";
    }

    auto [parsedProtParams, _, errMsg] = cppbor::parse(protectedParams);
    if (!parsedProtParams) {
        return errMsg + " when parsing protected params.";
    }
    if (!parsedProtParams->asMap()) {
        return "Protected params must be a map";
    }

    auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM);
    if (!algorithm || !algorithm->asInt() ||
        !(algorithm->asInt()->value() == EDDSA || algorithm->asInt()->value() == ES256)) {
        return "Unsupported signature algorithm";
    }

    const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
    if (!signature || signature->value().empty()) {
        return "Missing signature input";
    }

    bool selfSigned = signingCoseKey.empty();
    bytevec signatureInput =
        cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode();
    if (algorithm->asInt()->value() == EDDSA) {
        auto key = CoseKey::parseEd25519(selfSigned ? payload->value() : signingCoseKey);
        if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty()) {
            return "Bad signing key: " + key.moveMessage();
        }

        if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(),
                            key->getBstrValue(CoseKey::PUBKEY_X)->data())) {
            return "Signature verification failed";
        }
    } else {  // P256
        auto key = CoseKey::parseP256(selfSigned ? payload->value() : signingCoseKey);
        if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty() ||
            key->getBstrValue(CoseKey::PUBKEY_Y)->empty()) {
            return "Bad signing key: " + key.moveMessage();
        }
        auto publicKey = key->getEcPublicKey();
        if (!publicKey) return publicKey.moveMessage();

        auto ecdsaDerSignature = ecdsaCoseSignatureToDer(signature->value());
        if (!ecdsaDerSignature) return ecdsaDerSignature.moveMessage();

        // convert public key to uncompressed form by prepending 0x04 at begin.
        publicKey->insert(publicKey->begin(), 0x04);

        if (!verifyEcdsaDigest(publicKey.moveValue(), sha256(signatureInput), *ecdsaDerSignature)) {
            return "Signature verification failed";
        }
    }

    return payload->value();
}

ErrMsgOr<bytevec> createCoseEncryptCiphertext(const bytevec& key, const bytevec& nonce,
                                              const bytevec& protectedParams,
                                              const bytevec& plaintextPayload, const bytevec& aad) {
    auto ciphertext = aesGcmEncrypt(key, nonce,
                                    cppbor::Array()            // Enc strucure as AAD
                                        .add("Encrypt")        // Context
                                        .add(protectedParams)  // Protected
                                        .add(aad)              // External AAD
                                        .encode(),
                                    plaintextPayload);

    if (!ciphertext) return ciphertext.moveMessage();
    return ciphertext.moveValue();
}

ErrMsgOr<cppbor::Array> constructCoseEncrypt(const bytevec& key, const bytevec& nonce,
                                             const bytevec& plaintextPayload, const bytevec& aad,
                                             cppbor::Array recipients) {
    auto encryptProtectedHeader = cppbor::Map()  //
                                      .add(ALGORITHM, AES_GCM_256)
                                      .canonicalize()
                                      .encode();

    auto ciphertext =
        createCoseEncryptCiphertext(key, nonce, encryptProtectedHeader, plaintextPayload, aad);
    if (!ciphertext) return ciphertext.moveMessage();

    return cppbor::Array()
        .add(encryptProtectedHeader)                       // Protected
        .add(cppbor::Map().add(IV, nonce).canonicalize())  // Unprotected
        .add(*ciphertext)                                  // Payload
        .add(std::move(recipients));
}

ErrMsgOr<std::pair<bytevec /* pubkey */, bytevec /* key ID */>>
getSenderPubKeyFromCoseEncrypt(const cppbor::Item* coseEncrypt) {
    if (!coseEncrypt || !coseEncrypt->asArray() ||
        coseEncrypt->asArray()->size() != kCoseEncryptEntryCount) {
        return "Invalid COSE_Encrypt";
    }

    auto& recipients = coseEncrypt->asArray()->get(kCoseEncryptRecipients);
    if (!recipients || !recipients->asArray() || recipients->asArray()->size() != 1) {
        return "Invalid recipients list";
    }

    auto& recipient = recipients->asArray()->get(0);
    if (!recipient || !recipient->asArray() || recipient->asArray()->size() != 3) {
        return "Invalid COSE_recipient";
    }

    auto& ciphertext = recipient->asArray()->get(2);
    if (!ciphertext->asSimple() || !ciphertext->asSimple()->asNull()) {
        return "Unexpected value in recipients ciphertext field " +
               cppbor::prettyPrint(ciphertext.get());
    }

    auto& protParms = recipient->asArray()->get(0);
    if (!protParms || !protParms->asBstr()) return "Invalid protected params";
    auto [parsedProtParms, _, errMsg] = cppbor::parse(protParms->asBstr());
    if (!parsedProtParms) return "Failed to parse protected params: " + errMsg;
    if (!parsedProtParms->asMap()) return "Invalid protected params";

    auto& algorithm = parsedProtParms->asMap()->get(ALGORITHM);
    if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != ECDH_ES_HKDF_256) {
        return "Invalid algorithm";
    }

    auto& unprotParms = recipient->asArray()->get(1);
    if (!unprotParms || !unprotParms->asMap()) return "Invalid unprotected params";

    auto& senderCoseKey = unprotParms->asMap()->get(COSE_KEY);
    if (!senderCoseKey || !senderCoseKey->asMap()) return "Invalid sender COSE_Key";

    auto& keyType = senderCoseKey->asMap()->get(CoseKey::KEY_TYPE);
    if (!keyType || !keyType->asInt() ||
        (keyType->asInt()->value() != OCTET_KEY_PAIR && keyType->asInt()->value() != EC2)) {
        return "Invalid key type";
    }

    auto& curve = senderCoseKey->asMap()->get(CoseKey::CURVE);
    if (!curve || !curve->asInt() ||
        (keyType->asInt()->value() == OCTET_KEY_PAIR && curve->asInt()->value() != X25519) ||
        (keyType->asInt()->value() == EC2 && curve->asInt()->value() != P256)) {
        return "Unsupported curve";
    }

    bytevec publicKey;
    if (keyType->asInt()->value() == EC2) {
        auto& pubX = senderCoseKey->asMap()->get(CoseKey::PUBKEY_X);
        if (!pubX || !pubX->asBstr() || pubX->asBstr()->value().size() != kP256AffinePointSize) {
            return "Invalid EC public key";
        }
        auto& pubY = senderCoseKey->asMap()->get(CoseKey::PUBKEY_Y);
        if (!pubY || !pubY->asBstr() || pubY->asBstr()->value().size() != kP256AffinePointSize) {
            return "Invalid EC public key";
        }
        auto key = CoseKey::getEcPublicKey(pubX->asBstr()->value(), pubY->asBstr()->value());
        if (!key) return key.moveMessage();
        publicKey = key.moveValue();
    } else {
        auto& pubkey = senderCoseKey->asMap()->get(CoseKey::PUBKEY_X);
        if (!pubkey || !pubkey->asBstr() ||
            pubkey->asBstr()->value().size() != X25519_PUBLIC_VALUE_LEN) {
            return "Invalid X25519 public key";
        }
        publicKey = pubkey->asBstr()->value();
    }

    auto& key_id = unprotParms->asMap()->get(KEY_ID);
    if (key_id && key_id->asBstr()) {
        return std::make_pair(publicKey, key_id->asBstr()->value());
    }

    // If no key ID, just return an empty vector.
    return std::make_pair(publicKey, bytevec{});
}

ErrMsgOr<bytevec> decryptCoseEncrypt(const bytevec& key, const cppbor::Item* coseEncrypt,
                                     const bytevec& external_aad) {
    if (!coseEncrypt || !coseEncrypt->asArray() ||
        coseEncrypt->asArray()->size() != kCoseEncryptEntryCount) {
        return "Invalid COSE_Encrypt";
    }

    auto& protParms = coseEncrypt->asArray()->get(kCoseEncryptProtectedParams);
    auto& unprotParms = coseEncrypt->asArray()->get(kCoseEncryptUnprotectedParams);
    auto& ciphertext = coseEncrypt->asArray()->get(kCoseEncryptPayload);
    auto& recipients = coseEncrypt->asArray()->get(kCoseEncryptRecipients);

    if (!protParms || !protParms->asBstr() || !unprotParms || !ciphertext || !recipients) {
        return "Invalid COSE_Encrypt";
    }

    auto [parsedProtParams, _, errMsg] = cppbor::parse(protParms->asBstr()->value());
    if (!parsedProtParams) {
        return errMsg + " when parsing protected params.";
    }
    if (!parsedProtParams->asMap()) {
        return "Protected params must be a map";
    }

    auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM);
    if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != AES_GCM_256) {
        return "Unsupported encryption algorithm";
    }

    if (!unprotParms->asMap() || unprotParms->asMap()->size() != 1) {
        return "Invalid unprotected params";
    }

    auto& nonce = unprotParms->asMap()->get(IV);
    if (!nonce || !nonce->asBstr() || nonce->asBstr()->value().size() != kAesGcmNonceLength) {
        return "Invalid nonce";
    }

    if (!ciphertext->asBstr()) return "Invalid ciphertext";

    auto aad = cppbor::Array()                         // Enc strucure as AAD
                   .add("Encrypt")                     // Context
                   .add(protParms->asBstr()->value())  // Protected
                   .add(external_aad)                  // External AAD
                   .encode();

    return aesGcmDecrypt(key, nonce->asBstr()->value(), aad, ciphertext->asBstr()->value());
}

ErrMsgOr<bytevec> consructKdfContext(const bytevec& pubKeyA, const bytevec& privKeyA,
                                     const bytevec& pubKeyB, bool senderIsA) {
    if (privKeyA.empty() || pubKeyA.empty() || pubKeyB.empty()) {
        return "Missing input key parameters";
    }

    bytevec kdfContext = cppbor::Array()
                             .add(AES_GCM_256)
                             .add(cppbor::Array()  // Sender Info
                                      .add(cppbor::Bstr("client"))
                                      .add(bytevec{} /* nonce */)
                                      .add(senderIsA ? pubKeyA : pubKeyB))
                             .add(cppbor::Array()  // Recipient Info
                                      .add(cppbor::Bstr("server"))
                                      .add(bytevec{} /* nonce */)
                                      .add(senderIsA ? pubKeyB : pubKeyA))
                             .add(cppbor::Array()               // SuppPubInfo
                                      .add(kAesGcmKeySizeBits)  // output key length
                                      .add(bytevec{}))          // protected
                             .encode();
    return kdfContext;
}

ErrMsgOr<bytevec> ECDH_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& privKeyA,
                                      const bytevec& pubKeyB, bool senderIsA) {
    if (privKeyA.empty() || pubKeyA.empty() || pubKeyB.empty()) {
        return "Missing input key parameters";
    }

    // convert public key to uncompressed form by prepending 0x04 at begin
    bytevec publicKey;
    publicKey.insert(publicKey.begin(), 0x04);
    publicKey.insert(publicKey.end(), pubKeyB.begin(), pubKeyB.end());
    auto rawSharedKey = ecdh(publicKey, privKeyA);
    if (!rawSharedKey) return rawSharedKey.moveMessage();

    auto kdfContext = consructKdfContext(pubKeyA, privKeyA, pubKeyB, senderIsA);
    if (!kdfContext) return kdfContext.moveMessage();

    bytevec retval(SHA256_DIGEST_LENGTH);
    bytevec salt{};
    if (!HKDF(retval.data(), retval.size(),                //
              EVP_sha256(),                                //
              rawSharedKey->data(), rawSharedKey->size(),  //
              salt.data(), salt.size(),                    //
              kdfContext->data(), kdfContext->size())) {
        return "ECDH HKDF failed";
    }

    return retval;
}

ErrMsgOr<bytevec> x25519_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& privKeyA,
                                        const bytevec& pubKeyB, bool senderIsA) {
    if (privKeyA.empty() || pubKeyA.empty() || pubKeyB.empty()) {
        return "Missing input key parameters";
    }

    bytevec rawSharedKey(X25519_SHARED_KEY_LEN);
    if (!::X25519(rawSharedKey.data(), privKeyA.data(), pubKeyB.data())) {
        return "ECDH operation failed";
    }

    auto kdfContext = consructKdfContext(pubKeyA, privKeyA, pubKeyB, senderIsA);
    if (!kdfContext) return kdfContext.moveMessage();

    bytevec retval(SHA256_DIGEST_LENGTH);
    bytevec salt{};
    if (!HKDF(retval.data(), retval.size(),              //
              EVP_sha256(),                              //
              rawSharedKey.data(), rawSharedKey.size(),  //
              salt.data(), salt.size(),                  //
              kdfContext->data(), kdfContext->size())) {
        return "ECDH HKDF failed";
    }

    return retval;
}

ErrMsgOr<bytevec> aesGcmEncrypt(const bytevec& key, const bytevec& nonce, const bytevec& aad,
                                const bytevec& plaintext) {
    auto ctx = aesGcmInitAndProcessAad(key, nonce, aad, true /* encrypt */);
    if (!ctx) return ctx.moveMessage();

    bytevec ciphertext(plaintext.size() + kAesGcmTagSize);
    int outlen;
    if (!EVP_CipherUpdate(ctx->get(), ciphertext.data(), &outlen, plaintext.data(),
                          plaintext.size())) {
        return "Failed to encrypt plaintext";
    }
    assert(plaintext.size() == static_cast<uint64_t>(outlen));

    if (!EVP_CipherFinal_ex(ctx->get(), ciphertext.data() + outlen, &outlen)) {
        return "Failed to finalize encryption";
    }
    assert(outlen == 0);

    if (!EVP_CIPHER_CTX_ctrl(ctx->get(), EVP_CTRL_GCM_GET_TAG, kAesGcmTagSize,
                             ciphertext.data() + plaintext.size())) {
        return "Failed to retrieve tag";
    }

    return ciphertext;
}

ErrMsgOr<bytevec> aesGcmDecrypt(const bytevec& key, const bytevec& nonce, const bytevec& aad,
                                const bytevec& ciphertextWithTag) {
    auto ctx = aesGcmInitAndProcessAad(key, nonce, aad, false /* encrypt */);
    if (!ctx) return ctx.moveMessage();

    if (ciphertextWithTag.size() < kAesGcmTagSize) return "Missing tag";

    bytevec plaintext(ciphertextWithTag.size() - kAesGcmTagSize);
    int outlen;
    if (!EVP_CipherUpdate(ctx->get(), plaintext.data(), &outlen, ciphertextWithTag.data(),
                          ciphertextWithTag.size() - kAesGcmTagSize)) {
        return "Failed to decrypt plaintext";
    }
    assert(plaintext.size() == static_cast<uint64_t>(outlen));

    bytevec tag(ciphertextWithTag.end() - kAesGcmTagSize, ciphertextWithTag.end());
    if (!EVP_CIPHER_CTX_ctrl(ctx->get(), EVP_CTRL_GCM_SET_TAG, kAesGcmTagSize, tag.data())) {
        return "Failed to set tag: " + std::to_string(ERR_peek_last_error());
    }

    if (!EVP_CipherFinal_ex(ctx->get(), nullptr, &outlen)) {
        return "Failed to finalize encryption";
    }
    assert(outlen == 0);

    return plaintext;
}

bytevec sha256(const bytevec& data) {
    bytevec ret(SHA256_DIGEST_LENGTH);
    SHA256_CTX ctx;
    SHA256_Init(&ctx);
    SHA256_Update(&ctx, data.data(), data.size());
    SHA256_Final((unsigned char*)ret.data(), &ctx);
    return ret;
}

bool verifyEcdsaDigest(const bytevec& key, const bytevec& digest, const bytevec& signature) {
    const unsigned char* p = (unsigned char*)signature.data();
    auto sig = ECDSA_SIG_Ptr(d2i_ECDSA_SIG(nullptr, &p, signature.size()));
    if (sig.get() == nullptr) {
        return false;
    }

    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
    auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
    if (EC_POINT_oct2point(group.get(), point.get(), key.data(), key.size(), nullptr) != 1) {
        return false;
    }
    auto ecKey = EC_KEY_Ptr(EC_KEY_new());
    if (ecKey.get() == nullptr) {
        return false;
    }
    if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
        return false;
    }
    if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
        return false;
    }

    int rc = ECDSA_do_verify(digest.data(), digest.size(), sig.get(), ecKey.get());
    if (rc != 1) {
        return false;
    }
    return true;
}

}  // namespace cppcose
