/**
 *    Copyright (c) 2022 Project CHIP Authors
 *
 *    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.
 */

#import "MTRDeviceControllerStartupParams.h"
#import "MTRCertificates.h"
#import "MTRDeviceControllerStartupParams_Internal.h"
#import "MTRLogging_Internal.h"
#import "MTRP256KeypairBridge.h"
#import "NSDataSpanConversion.h"

#include <controller/OperationalCredentialsDelegate.h>
#include <credentials/CHIPCert.h>
#include <credentials/FabricTable.h>
#include <lib/core/PeerId.h>

using namespace chip;

@implementation MTRDeviceControllerStartupParams

- (instancetype)initWithIPK:(NSData *)ipk fabricID:(NSNumber *)fabricID nocSigner:(id<MTRKeypair>)nocSigner
{
    if (!(self = [super init])) {
        return nil;
    }

    if (!IsValidFabricId(fabricID.unsignedLongLongValue)) {
        MTR_LOG_ERROR("%llu is not a valid fabric id to initialize a device controller with", fabricID.unsignedLongLongValue);
        return nil;
    }

    _nocSigner = nocSigner;
    _fabricID = [fabricID copy];
    _ipk = [ipk copy];

    return self;
}

- (instancetype)initWithIPK:(NSData *)ipk
         operationalKeypair:(id<MTRKeypair>)operationalKeypair
     operationalCertificate:(MTRCertificateDERBytes)operationalCertificate
    intermediateCertificate:(MTRCertificateDERBytes _Nullable)intermediateCertificate
            rootCertificate:(MTRCertificateDERBytes)rootCertificate
{
    if (!(self = [super init])) {
        return nil;
    }

    { // Scope for temporaries
        // ExtractNodeIdFabricIdFromOpCert needs a TLV-encoded opcert, not a DER-encoded one.
        uint8_t tlvOpCertBuf[Credentials::kMaxCHIPCertLength];
        MutableByteSpan tlvOpCert(tlvOpCertBuf);
        CHIP_ERROR err = Credentials::ConvertX509CertToChipCert(AsByteSpan(operationalCertificate), tlvOpCert);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Unable to convert operational certificate to TLV: %s", ErrorStr(err));
            return nil;
        }

        FabricId fabricId = kUndefinedFabricId;
        NodeId unused = kUndefinedNodeId;
        err = Credentials::ExtractNodeIdFabricIdFromOpCert(tlvOpCert, &unused, &fabricId);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Unable to extract fabric id from operational certificate: %s", ErrorStr(err));
            return nil;
        }
        _fabricID = @(fabricId);
    }

    _operationalKeypair = operationalKeypair;
    _operationalCertificate = [operationalCertificate copy];
    _intermediateCertificate = [intermediateCertificate copy];
    _rootCertificate = [rootCertificate copy];
    _ipk = [ipk copy];

    return self;
}

- (instancetype)initWithParams:(MTRDeviceControllerStartupParams *)params
{
    if (!(self = [super init])) {
        return nil;
    }

    _nocSigner = params.nocSigner;
    _fabricID = params.fabricID;
    _ipk = params.ipk;
    _vendorID = params.vendorID;
    _nodeID = params.nodeID;
    _rootCertificate = params.rootCertificate;
    _intermediateCertificate = params.intermediateCertificate;
    _operationalCertificate = params.operationalCertificate;
    _operationalKeypair = params.operationalKeypair;

    return self;
}

@end

// Convert a ByteSpan representing a Matter TLV certificate into NSData holding
// a DER X.509 certificate.  Returns nil on failures.
static NSData * _Nullable MatterCertToX509Data(const ByteSpan & cert)
{
    uint8_t buf[Controller::kMaxCHIPDERCertLength];
    MutableByteSpan derCert(buf);
    CHIP_ERROR err = Credentials::ConvertChipCertToX509Cert(cert, derCert);
    if (err != CHIP_NO_ERROR) {
        MTR_LOG_ERROR("Failed do convert Matter certificate to X.509 DER: %s", ErrorStr(err));
        return nil;
    }

    return AsData(derCert);
}

@implementation MTRDeviceControllerStartupParams (Deprecated)

- (uint64_t)fabricId
{
    return self.fabricID.unsignedLongLongValue;
}

- (nullable NSNumber *)vendorId
{
    return self.vendorID;
}

- (void)setVendorId:(nullable NSNumber *)vendorId
{
    self.vendorID = vendorId;
}

- (nullable NSNumber *)nodeId
{
    return self.nodeID;
}

- (void)setNodeId:(nullable NSNumber *)nodeId
{
    self.nodeID = nodeId;
}

- (instancetype)initWithSigningKeypair:(id<MTRKeypair>)nocSigner fabricId:(uint64_t)fabricId ipk:(NSData *)ipk
{
    return [self initWithIPK:ipk fabricID:@(fabricId) nocSigner:nocSigner];
}

- (instancetype)initWithOperationalKeypair:(id<MTRKeypair>)operationalKeypair
                    operationalCertificate:(MTRCertificateDERBytes)operationalCertificate
                   intermediateCertificate:(MTRCertificateDERBytes _Nullable)intermediateCertificate
                           rootCertificate:(MTRCertificateDERBytes)rootCertificate
                                       ipk:(NSData *)ipk
{
    return [self initWithIPK:ipk
             operationalKeypair:operationalKeypair
         operationalCertificate:operationalCertificate
        intermediateCertificate:intermediateCertificate
                rootCertificate:rootCertificate];
}

@end

@implementation MTRDeviceControllerStartupParamsInternal

- (instancetype)initWithParams:(MTRDeviceControllerStartupParams *)params
{
    if (!(self = [super initWithParams:params])) {
        return nil;
    }

    if (self.nocSigner == nil && self.rootCertificate == nil) {
        MTR_LOG_ERROR("nocSigner and rootCertificate are both nil; no public key available to identify the fabric");
        return nil;
    }

    if (self.operationalCertificate != nil && self.nodeID != nil) {
        MTR_LOG_ERROR("nodeID must be nil if operationalCertificate is not nil");
        return nil;
    }

    if (self.operationalCertificate != nil) {
        if (self.operationalKeypair == nil) {
            MTR_LOG_ERROR("Must have an operational keypair if an operational certificate is provided");
            return nil;
        }

        if (![MTRCertificates keypair:self.operationalKeypair matchesCertificate:self.operationalCertificate]) {
            MTR_LOG_ERROR("operationalKeypair public key does not match operationalCertificate");
            return nil;
        }
    }

    return self;
}

- (instancetype)initForNewFabric:(chip::FabricTable *)fabricTable
                        keystore:(chip::Crypto::OperationalKeystore *)keystore
                          params:(MTRDeviceControllerStartupParams *)params
{
    if (!(self = [self initWithParams:params])) {
        return nil;
    }

    if (self.nocSigner == nil && self.operationalCertificate == nil) {
        MTR_LOG_ERROR("No way to get an operational certificate: nocSigner and operationalCertificate are both nil");
        return nil;
    }

    if (self.operationalCertificate == nil && self.nodeID == nil) {
        // Just avoid setting the top bit, to avoid issues with node
        // ids outside the operational range.
        uint64_t nodeId = arc4random();
        nodeId = (nodeId << 31) | (arc4random() >> 1);
        self.nodeID = @(nodeId);
    }

    if (self.rootCertificate == nil) {
        NSError * error;
        self.rootCertificate = [MTRCertificates createRootCertificate:self.nocSigner
                                                             issuerID:nil
                                                             fabricID:self.fabricID
                                                                error:&error];
        if (error != nil || self.rootCertificate == nil) {
            MTR_LOG_ERROR("Failed to generate root certificate: %@", error);
            return nil;
        }
    }

    _fabricTable = fabricTable;
    _keystore = keystore;

    return self;
}

- (instancetype)initForExistingFabric:(FabricTable *)fabricTable
                          fabricIndex:(FabricIndex)fabricIndex
                             keystore:(chip::Crypto::OperationalKeystore *)keystore
                               params:(MTRDeviceControllerStartupParams *)params
{
    if (!(self = [self initWithParams:params])) {
        return nil;
    }

    const FabricInfo * fabric = fabricTable->FindFabricWithIndex(fabricIndex);

    if (self.vendorID == nil) {
        self.vendorID = @(fabric->GetVendorId());
    }

    BOOL usingExistingNOC = NO;
    if (self.operationalCertificate == nil && self.nodeID == nil) {
        self.nodeID = @(fabric->GetNodeId());

        if (self.operationalKeypair == nil) {
            uint8_t nocBuf[Credentials::kMaxCHIPCertLength];
            MutableByteSpan noc(nocBuf);
            CHIP_ERROR err = fabricTable->FetchNOCCert(fabric->GetFabricIndex(), noc);
            if (err != CHIP_NO_ERROR) {
                MTR_LOG_ERROR("Failed to get existing NOC: %s", ErrorStr(err));
                return nil;
            }
            self.operationalCertificate = MatterCertToX509Data(noc);
            if (self.operationalCertificate == nil) {
                MTR_LOG_ERROR("Failed to convert TLV NOC to DER X.509: %s", ErrorStr(err));
                return nil;
            }
            if (!keystore->HasOpKeypairForFabric(fabric->GetFabricIndex())) {
                MTR_LOG_ERROR("No existing operational key for fabric");
                return nil;
            }
        }

        usingExistingNOC = YES;
    }

    NSData * oldIntermediateCert = nil;
    {
        uint8_t icaBuf[Credentials::kMaxCHIPCertLength];
        MutableByteSpan icaCert(icaBuf);
        CHIP_ERROR err = fabricTable->FetchICACert(fabric->GetFabricIndex(), icaCert);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Failed to get existing intermediate certificate: %s", ErrorStr(err));
            return nil;
        }
        // There might not be an ICA cert for this fabric.
        if (!icaCert.empty()) {
            oldIntermediateCert = MatterCertToX509Data(icaCert);
            if (oldIntermediateCert == nil) {
                return nil;
            }
        }
    }

    if (self.nocSigner != nil && self.intermediateCertificate == nil && oldIntermediateCert != nil) {
        // It's possible that we are switching from using an ICA cert to not using
        // one.  We can detect this case by checking whether the provided nocSigner
        // matches the ICA cert.
        if ([MTRCertificates keypair:self.nocSigner matchesCertificate:oldIntermediateCert] == YES) {
            // Keep using the existing intermediate certificate.
            self.intermediateCertificate = oldIntermediateCert;
        }
        // else presumably the nocSigner matches the root (will be verified later)
        // and we are no longer using an intermediate.
    }

    // If we were planning to use our existing NOC from the fabric info but we are
    // changing from having an ICA to not having one, or changing from having one
    // to not having one, or changing the identity of our ICA, we need to generate
    // a new NOC.  But we can keep our existing operational keypair and node id;
    // nothing is forcing us to rotate those.
    if (usingExistingNOC == YES
        && ((oldIntermediateCert == nil) != (self.intermediateCertificate == nil)
            || ((oldIntermediateCert != nil) &&
                [MTRCertificates isCertificate:oldIntermediateCert equalTo:self.intermediateCertificate] == NO))) {
        self.operationalCertificate = nil;
    }

    NSData * oldRootCert;
    {
        uint8_t rootBuf[Credentials::kMaxCHIPCertLength];
        MutableByteSpan rootCert(rootBuf);
        CHIP_ERROR err = fabricTable->FetchRootCert(fabric->GetFabricIndex(), rootCert);
        if (err != CHIP_NO_ERROR) {
            MTR_LOG_ERROR("Failed to get existing root certificate: %s", ErrorStr(err));
            return nil;
        }
        oldRootCert = MatterCertToX509Data(rootCert);
        if (oldRootCert == nil) {
            return nil;
        }
    }

    if (self.rootCertificate == nil) {
        self.rootCertificate = oldRootCert;
    } else if ([MTRCertificates isCertificate:oldRootCert equalTo:self.rootCertificate] == NO) {
        MTR_LOG_ERROR("Root certificate identity does not match existing root certificate");
        return nil;
    }

    _fabricTable = fabricTable;
    _fabricIndex.Emplace(fabricIndex);
    _keystore = keystore;

    return self;
}

- (BOOL)keypairsMatchCertificates
{
    if (self.nocSigner != nil) {
        NSData * signingCert = self.intermediateCertificate;
        if (signingCert == nil) {
            signingCert = self.rootCertificate;
            if (signingCert == nil) {
                MTR_LOG_ERROR("No certificate to match nocSigner");
                return NO;
            }
        }

        if ([MTRCertificates keypair:self.nocSigner matchesCertificate:signingCert] == NO) {
            MTR_LOG_ERROR("Provided nocSigner does not match certificates");
            return NO;
        }
    }

    if (self.operationalCertificate != nil && self.operationalKeypair != nil) {
        if ([MTRCertificates keypair:self.operationalKeypair matchesCertificate:self.operationalCertificate] == NO) {
            MTR_LOG_ERROR("Provided operationalKeypair does not match operationalCertificate");
            return NO;
        }
    }

    return YES;
}

@end
