"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var VendorIdVerification_exports = {};
__export(VendorIdVerification_exports, {
  VERIFICATION_STATEMENT_SIZE: () => VERIFICATION_STATEMENT_SIZE,
  VendorIdVerification: () => VendorIdVerification
});
module.exports = __toCommonJS(VendorIdVerification_exports);
var import_general = require("#general");
var import_protocol = require("#protocol");
var import_types = require("#types");
var import_OperationalCredentialsClient = require("../operational-credentials/OperationalCredentialsClient.js");
/**
 * @license
 * Copyright 2022-2025 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const logger = import_general.Logger.get("VendorIdVerification");
const VERIFICATION_STATEMENT_VERSION = 33;
const FABRIC_BINDING_MESSAGE_SIZE = 76;
const VERIFICATION_STATEMENT_SIZE = 85;
const FABRIC_BINDING_VERSION = import_general.MATTER_CRYPTO_PRIMITIVES_VERSION;
var VendorIdVerification;
((VendorIdVerification2) => {
  function dataToSign(data) {
    const {
      fabricBindingVersion = FABRIC_BINDING_VERSION,
      clientChallenge,
      attChallenge,
      fabricIndex,
      fabric
    } = data;
    if (fabricBindingVersion !== FABRIC_BINDING_VERSION) {
      throw new import_general.InternalError(`Unsupported Fabric Binding Version ${fabricBindingVersion}`);
    }
    const tbsWriter = new import_general.DataWriter(import_general.Endian.Big);
    tbsWriter.writeUInt8(fabricBindingVersion);
    tbsWriter.writeByteArray(clientChallenge);
    tbsWriter.writeByteArray(attChallenge);
    tbsWriter.writeUInt8(fabricIndex);
    tbsWriter.writeUInt8(fabricBindingVersion);
    tbsWriter.writeByteArray(fabric.rootPublicKey);
    tbsWriter.writeUInt64(fabric.fabricId);
    tbsWriter.writeUInt16(fabric.rootVendorId);
    if (fabric.vidVerificationStatement) {
      tbsWriter.writeByteArray(fabric.vidVerificationStatement);
    }
    return {
      fabricBindingVersion,
      signatureData: tbsWriter.toByteArray()
    };
  }
  VendorIdVerification2.dataToSign = dataToSign;
  async function verify(node, options) {
    const crypto = node.env.get(import_general.Crypto);
    const clientChallenge = crypto.randomBytes(32);
    const {
      fabric: { fabricIndex }
    } = options;
    let signVerificationResponse;
    try {
      signVerificationResponse = await node.commandsOf(import_OperationalCredentialsClient.OperationalCredentialsClient).signVidVerificationRequest({ fabricIndex, clientChallenge });
      if (fabricIndex !== signVerificationResponse.fabricIndex) {
        throw new import_types.StatusResponse.InvalidCommandError(
          `Fabric Index mismatch: expected ${fabricIndex}, got ${signVerificationResponse.fabricIndex}`
        );
      }
    } catch (error) {
      import_types.ReceivedStatusResponseError.accept(error);
      logger.error("Could not verify VendorId", error);
      return void 0;
    }
    const session = node.interaction.session;
    if (session === void 0 || !import_protocol.NodeSession.is(session)) {
      logger.error("Could not verify VendorId: no session established");
      return void 0;
    }
    const { noc, rcac, fabric } = options;
    return await verifyData(crypto, {
      clientChallenge,
      attChallenge: session.attestationChallengeKey,
      signVerificationResponse,
      noc,
      rcac,
      fabric
    });
  }
  VendorIdVerification2.verify = verify;
  async function verifyData(crypto, options) {
    const {
      clientChallenge,
      attChallenge,
      signVerificationResponse: { fabricBindingVersion, signature },
      noc: { noc, icac, vvsc },
      rcac,
      fabric: { vendorId: rootVendorId, vidVerificationStatement, fabricIndex }
    } = options;
    const {
      subject: { fabricId },
      ellipticCurvePublicKey: rootPublicKey
    } = import_protocol.Noc.fromTlv(noc).cert;
    const tbs = dataToSign({
      fabricBindingVersion,
      clientChallenge,
      attChallenge,
      fabricIndex,
      fabric: {
        rootPublicKey,
        fabricId,
        rootVendorId,
        vidVerificationStatement
      }
    }).signatureData;
    try {
      await crypto.verifyEcdsa((0, import_general.PublicKey)(rootPublicKey), tbs, new import_general.EcdsaSignature(signature));
      const rootCert = import_protocol.Rcac.fromTlv(rcac);
      const nocCert = import_protocol.Noc.fromTlv(noc);
      const icaCert = icac ? import_protocol.Icac.fromTlv(icac) : void 0;
      if (icaCert !== void 0) {
        await icaCert.verify(crypto, rootCert);
      }
      await nocCert.verify(crypto, rootCert, icaCert);
    } catch (error) {
      import_general.CryptoError.accept(error);
      logger.error("Could not verify VendorId", error);
      return false;
    }
    if (vidVerificationStatement) {
      const {
        signerSkid,
        version: vidStatementVersion,
        signature: vidStatementSignature
      } = parseStatement(vidVerificationStatement);
      if (vidStatementSignature === void 0) {
        throw new import_general.UnexpectedDataError("VID Verification Statement is missing signature");
      }
      let vvscCert;
      if (vvsc !== void 0) {
        vvscCert = import_protocol.Vvsc.fromTlv(vvsc);
      } else {
        return true;
      }
      const {
        extensions: { subjectKeyIdentifier },
        ellipticCurvePublicKey
      } = vvscCert.cert;
      if (!import_general.Bytes.areEqual(subjectKeyIdentifier, signerSkid)) {
        throw new import_general.UnexpectedDataError(
          `VVSC SubjectKeyIdentifier does not match signerSkid in VID Verification Statement`
        );
      }
      await vvscCert.verify(crypto);
      const ourStatement = createStatementBytes({
        version: vidStatementVersion,
        fabricBindingMessage: tbs,
        signerSkid
      });
      await crypto.verifyEcdsa(
        (0, import_general.PublicKey)(ellipticCurvePublicKey),
        ourStatement,
        new import_general.EcdsaSignature(vidStatementSignature)
      );
    } else {
    }
    return true;
  }
  VendorIdVerification2.verifyData = verifyData;
  function createStatementBytes(options) {
    const { version = VERIFICATION_STATEMENT_VERSION, fabricBindingMessage, signerSkid } = options;
    const writer = new import_general.DataWriter();
    writer.writeUInt8(version);
    writer.writeByteArray(fabricBindingMessage);
    writer.writeByteArray(signerSkid);
    return writer.toByteArray();
  }
  VendorIdVerification2.createStatementBytes = createStatementBytes;
  function parseStatement(statement) {
    const reader = new import_general.DataReader(statement);
    const version = reader.readUInt8();
    if (version !== VERIFICATION_STATEMENT_VERSION) {
      throw new import_general.UnexpectedDataError(`Unsupported VID Verification Statement version ${version}`);
    }
    const fabricBindingMessage = reader.readByteArray(FABRIC_BINDING_MESSAGE_SIZE);
    const signerSkid = reader.readByteArray(20);
    const signature = reader.remainingBytesCount > 0 ? reader.remainingBytes : void 0;
    return {
      version,
      fabricBindingMessage,
      signerSkid,
      signature
    };
  }
  VendorIdVerification2.parseStatement = parseStatement;
})(VendorIdVerification || (VendorIdVerification = {}));
//# sourceMappingURL=VendorIdVerification.js.map
