"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SevSNP = exports.getDefaultArkHashes = exports.ARK_GENOA = exports.ARK_MILAN = exports.EMPTY_INITRD_SHA256_HASH = exports.AMD_EPYC_MILAN_CPUINFO = exports.SupportedAmdSevSnpGenerations = void 0;
const amd_sev_snp_napi_rs_1 = require("../../bindings/amd-sev-snp-napi-rs/");
const sdk_js_1 = require("@super-protocol/sdk-js");
const axios_1 = __importDefault(require("axios"));
const forge = __importStar(require("node-forge"));
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const os = __importStar(require("os"));
const child_process_1 = require("child_process");
const crypto_1 = require("crypto");
const helpers_1 = require("./helpers");
const AmdSevSnp_1 = require("../proto/AmdSevSnp");
var SupportedAmdSevSnpGenerations;
(function (SupportedAmdSevSnpGenerations) {
    SupportedAmdSevSnpGenerations["Milan"] = "Milan";
    SupportedAmdSevSnpGenerations["Genoa"] = "Genoa";
})(SupportedAmdSevSnpGenerations || (exports.SupportedAmdSevSnpGenerations = SupportedAmdSevSnpGenerations = {}));
exports.AMD_EPYC_MILAN_CPUINFO = {
    family: 25,
    model: 1,
    stepping: 1,
};
exports.EMPTY_INITRD_SHA256_HASH = Buffer.from("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "hex");
exports.ARK_MILAN = `-----BEGIN CERTIFICATE-----
MIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC
BQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS
BgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg
Q2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp
Y2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy
MTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS
BgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j
ZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG
9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg
W41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta
1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2
SzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0
60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05
gmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg
bKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs
+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi
Qi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ
eTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18
fHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j
WhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI
rFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG
KWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG
SIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI
AWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel
ETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw
STjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK
dHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq
zT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp
KGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e
pmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq
HnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh
3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn
JZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH
CViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4
AFZEAwoKCQ==
-----END CERTIFICATE-----`;
exports.ARK_GENOA = `-----BEGIN CERTIFICATE-----
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
/wMz1R1BHg==
-----END CERTIFICATE-----`;
function getDefaultArkHashes() {
    const ark_hashes = {};
    ark_hashes["ARK-Milan"] = SevSNP.getCertHash({
        type: AmdSevSnp_1.SevSNPCertType.ARK,
        format: AmdSevSnp_1.SevSnpCertificateFormat.PEM,
        cert: Buffer.from(exports.ARK_MILAN),
    });
    ark_hashes["ARK-Genoa"] = SevSNP.getCertHash({
        type: AmdSevSnp_1.SevSNPCertType.ARK,
        format: AmdSevSnp_1.SevSnpCertificateFormat.PEM,
        cert: Buffer.from(exports.ARK_GENOA),
    });
    return ark_hashes;
}
exports.getDefaultArkHashes = getDefaultArkHashes;
class SevSNP {
    static serializeSNPReport(report) {
        return Buffer.from(AmdSevSnp_1.SNPReportWithChain.encode(report).finish());
    }
    static deserializeSNPReport(serialized) {
        return AmdSevSnp_1.SNPReportWithChain.decode(serialized);
    }
    static convertCertToPem(cert) {
        const pemHeader = "-----BEGIN CERTIFICATE-----\n";
        const pemFooter = "\n-----END CERTIFICATE-----";
        if (cert.slice(0, pemHeader.length).compare(Buffer.from(pemHeader)) === 0) {
            return cert.toString();
        }
        const formattedBase64 = cert
            .toString("base64")
            .match(/.{1,64}/g)
            ?.join("\n");
        return pemHeader + formattedBase64 + pemFooter;
    }
    static convertPemToDer(cert) {
        return Buffer.from(forge.pki.pemToDer(cert).getBytes(), "binary");
    }
    static splitCerts(certsPem) {
        const certRegex = /-----BEGIN CERTIFICATE-----(?:\s|.)*?-----END CERTIFICATE-----/g;
        const matches = certsPem.match(certRegex);
        return Array.from(matches || []);
    }
    static async readCmdLine() {
        const data = await fs.readFile("/proc/cmdline", "utf-8");
        // Workaround: VM in direct boot mode sometimes adds to the end of the cmdline initrd=initrd, need to remove it
        return data.replace(/initrd=initrd\s*/, "");
    }
    /**
     * Method for generation AMD SEV-SNP Report
     * @param userData - The data that will be included in the report and will be signed
     */
    static async generateSNPReport(userData) {
        if (userData.length > amd_sev_snp_napi_rs_1.SNP_REPORT_DATA_SIZE) {
            throw new Error(`userData cannot exceed ${amd_sev_snp_napi_rs_1.SNP_REPORT_DATA_SIZE} bytes.`);
        }
        const paddedUserData = Buffer.alloc(64);
        userData.copy(paddedUserData);
        const rawReport = (0, amd_sev_snp_napi_rs_1.getSnpReport)(paddedUserData, 0);
        const cpuInfo = (0, amd_sev_snp_napi_rs_1.getCpuInfo)();
        const cpuSig = (0, amd_sev_snp_napi_rs_1.getCpuSig)(cpuInfo);
        const cores = (0, amd_sev_snp_napi_rs_1.getLogicalCoresCount)();
        const cmdLine = await SevSNP.readCmdLine();
        return {
            rawReport,
            cpuSig,
            cores,
            cmdLineHash: SevSNP.calculateCmdlineHash(cmdLine),
            build: SevSNP.extractBuildFromCmdline(cmdLine),
        };
    }
    /**
     * Method for fetch certificates from AMD KDS
     * @param report - report generated by the `generateSNPReport` method
     * @param options - options for working with HTTP, allows you to configure repetitions and the interval between them,
     *                  as well as the format of the returned certificates
     */
    static async getReportChain(report, options) {
        const retryMax = options?.retryMax ?? 2;
        const retryInterval = options?.retryInterval ?? 10000;
        const certFormat = options?.certFormat ?? AmdSevSnp_1.SevSnpCertificateFormat.DER;
        const certs = [];
        const axiosInstance = axios_1.default.create();
        let vcek = Buffer.alloc(0);
        let cpuGeneration = SupportedAmdSevSnpGenerations.Milan;
        const generations = Object.values(SupportedAmdSevSnpGenerations);
        for (const generation of generations) {
            cpuGeneration = generation;
            const vcekUrl = (0, amd_sev_snp_napi_rs_1.getVcekKdsUrl)(Buffer.from(report.rawReport), generation);
            try {
                const response = await sdk_js_1.helpers.tryWithInterval({
                    checkResult(response) {
                        return { isResultOk: response.status === 200 };
                    },
                    handler() {
                        return axiosInstance.get(vcekUrl, {
                            responseType: "arraybuffer",
                        });
                    },
                    checkError(err) {
                        if (axios_1.default.isAxiosError(err) && err.response) {
                            const status = err.response.status;
                            return { retryable: status == 429 };
                        }
                        return { retryable: axios_1.default.isAxiosError(err) };
                    },
                    retryInterval,
                    retryMax,
                });
                vcek = response.data;
                break;
            }
            catch (err) {
                const isLast = generation === generations[generations.length - 1];
                if (isLast) {
                    throw err;
                }
            }
        }
        const pemVcek = SevSNP.convertCertToPem(vcek);
        certs.push({
            type: AmdSevSnp_1.SevSNPCertType.VCEK,
            format: certFormat,
            cert: certFormat === AmdSevSnp_1.SevSnpCertificateFormat.PEM ? Buffer.from(pemVcek) : SevSNP.convertPemToDer(pemVcek),
        });
        const caUrl = `${amd_sev_snp_napi_rs_1.KDS_CERT_SITE}/${amd_sev_snp_napi_rs_1.KDS_VCEK}/${cpuGeneration}/cert_chain`;
        const response = await sdk_js_1.helpers.tryWithInterval({
            checkResult(response) {
                return { isResultOk: response.status === 200 };
            },
            handler() {
                return axiosInstance.get(caUrl, {
                    responseType: "arraybuffer",
                });
            },
            checkError(err) {
                if (axios_1.default.isAxiosError(err) && err.response) {
                    const status = err.response.status;
                    return { retryable: status == 429 };
                }
                return { retryable: axios_1.default.isAxiosError(err) };
            },
            retryInterval,
            retryMax,
        });
        const CAChain = SevSNP.splitCerts(response.data.toString());
        if (CAChain.length !== 2) {
            throw new Error("Cert chain must have 2 certificates");
        }
        certs.push({
            type: AmdSevSnp_1.SevSNPCertType.ARK,
            format: certFormat,
            cert: certFormat === AmdSevSnp_1.SevSnpCertificateFormat.PEM
                ? Buffer.from(CAChain[1])
                : SevSNP.convertPemToDer(CAChain[1]),
        });
        certs.push({
            type: AmdSevSnp_1.SevSNPCertType.ASK,
            format: certFormat,
            cert: certFormat === AmdSevSnp_1.SevSnpCertificateFormat.PEM
                ? Buffer.from(CAChain[0])
                : SevSNP.convertPemToDer(CAChain[0]),
        });
        return certs;
    }
    /**
     * Method for generation AMD SEV-SNP Report and fetching certificates
     * @param userData - @see generateSNPReport
     * @param options - @see getReportChain
     */
    static async generateSNPReportWithChain(userData, options) {
        const snpReport = await SevSNP.generateSNPReport(userData);
        const certs = await SevSNP.getReportChain(snpReport, options);
        return {
            snpReport,
            certs: certs,
        };
    }
    static async runSubProcess(binaryPath, args = [], options = {}) {
        return new Promise((resolve, reject) => {
            const subprocess = (0, child_process_1.spawn)(binaryPath, args, {
                cwd: options.cwd,
                stdio: "pipe",
            });
            let stdout = "";
            let stderr = "";
            subprocess.stdout?.on("data", (chunk) => (stdout += chunk.toString()));
            subprocess.stderr?.on("data", (chunk) => (stderr += chunk.toString()));
            let timeoutId;
            if (options.timeoutMs && options.timeoutMs > 0) {
                timeoutId = setTimeout(() => {
                    subprocess.kill();
                    reject(new Error(`Process timed out after ${options.timeoutMs}ms`));
                }, options.timeoutMs);
            }
            subprocess.on("close", (exitCode) => {
                if (timeoutId)
                    clearTimeout(timeoutId);
                resolve({
                    exitCode: exitCode || 0,
                    stdout,
                    stderr,
                });
            });
            subprocess.on("error", (error) => {
                if (timeoutId)
                    clearTimeout(timeoutId);
                reject(new Error(`Failed to start process: ${error.message}`));
            });
        });
    }
    static getCertHash(cert) {
        const hash = (0, crypto_1.createHash)("sha256");
        if (cert.format === AmdSevSnp_1.SevSnpCertificateFormat.PEM) {
            hash.update(SevSNP.convertPemToDer(cert.cert.toString()));
        }
        else {
            hash.update(cert.cert);
        }
        return hash.digest();
    }
    static isValidArk(ARK, trustedHashes) {
        const ArkCert = forge.pki.certificateFromPem(ARK.format === AmdSevSnp_1.SevSnpCertificateFormat.PEM
            ? ARK.cert.toString()
            : SevSNP.convertCertToPem(Buffer.from(ARK.cert)));
        const ArkCN = ArkCert.subject.attributes.find((attr) => attr.name === "commonName")?.value;
        if (!ArkCN) {
            throw new Error("Can't extract CN from ARK certificate");
        }
        const ArkHash = SevSNP.getCertHash(ARK);
        const TrustedHash = (trustedHashes && trustedHashes[ArkCN]) || Buffer.alloc(0);
        return ArkHash.equals(TrustedHash);
    }
    /**
     * AMD SEV-SNP verification method
     * @param report - report with full certificate chain
     * @param options - trustedHashes - map of trusted AMD ARK Certificates (CommonName as Key, Sha256 Hash of Der Certificate as Value) - optional
     *                  timeoutMs - timeout of the utility snpnost in ms
     *                  snpGuestBinaryPath - path for snpguest util
     */
    static async verifyReport(report, options) {
        const trustedHashes = options?.trustedHashes ?? getDefaultArkHashes();
        const timeoutMs = options?.timeoutMs ?? 10000;
        const snpGuestBinaryPath = options?.snpGuestBinaryPath ?? path.resolve(__dirname, "../../bindings/utils/virtee/snpguest");
        const tmpDirTemplate = options?.tmpDirTemplate ?? path.join(os.tmpdir(), "temp-");
        if (!path.isAbsolute(snpGuestBinaryPath)) {
            throw new Error("snpGuestBinaryPath must be an absolute path");
        }
        const ARK = report.certs.find((cert) => cert.type === AmdSevSnp_1.SevSNPCertType.ARK);
        if (!ARK) {
            throw new Error("Can't find ARK certificate in certificate chain");
        }
        if (!SevSNP.isValidArk(ARK, trustedHashes)) {
            throw new Error("The supplied certificate chain contains an untrusted root certificate");
        }
        const tempDir = await fs.mkdtemp(tmpDirTemplate);
        try {
            for (const certEntry of report.certs) {
                const fileName = (0, AmdSevSnp_1.sevSNPCertTypeToJSON)(certEntry.type).toLowerCase();
                const extension = certEntry.format === AmdSevSnp_1.SevSnpCertificateFormat.PEM ? "pem" : "der";
                await fs.writeFile(`${tempDir}/${fileName}.${extension}`, certEntry.cert, certEntry.format === AmdSevSnp_1.SevSnpCertificateFormat.PEM ? "utf8" : undefined);
            }
            const reportPath = `${tempDir}/report.bin`;
            await fs.writeFile(reportPath, Buffer.from(report.snpReport.rawReport));
            const snpguestRes = await SevSNP.runSubProcess(snpGuestBinaryPath, ["verify", "attestation", tempDir, reportPath], { timeoutMs });
            if (snpguestRes.exitCode != 0) {
                throw new Error(`Error validating report. Output: ${snpguestRes.stdout}\n${snpguestRes.stderr}`);
            }
        }
        finally {
            await (0, helpers_1.gramineCompatibleRmDir)(tempDir);
        }
    }
    static calcMrEnclave(measure, vmpl, policy) {
        const hash = (0, crypto_1.createHash)("sha256");
        hash.update(measure);
        const vmplBuf = Buffer.alloc(4);
        vmplBuf.writeUInt32LE(vmpl, 0);
        hash.update(vmplBuf);
        const policyBuf = Buffer.alloc(8);
        policyBuf.writeBigUint64LE(policy, 0);
        hash.update(policyBuf);
        return hash.digest();
    }
    /**
     * Method for obtaining mrEnclave from report. MrEnclave includes report measure, report vmpl and report policy
     * @param report - report without certificates
     */
    static getMrEnclave(report) {
        const measure = (0, amd_sev_snp_napi_rs_1.getReportMeasure)(report);
        const vmpl = (0, amd_sev_snp_napi_rs_1.getReportVmpl)(report);
        const policy = (0, amd_sev_snp_napi_rs_1.getReportPolicy)(report);
        return SevSNP.calcMrEnclave(measure, vmpl, policy);
    }
    /**
     * Method for obtaining reportData. This data was passed when generating the report
     * @param report - report without certificates
     */
    static async getReportData(report) {
        return (0, amd_sev_snp_napi_rs_1.getReportData)(report);
    }
    /**
     * Method for obtaining measure. Please do not confuse with mrenclave. Report measure is part of mrEnclave.
     * @param report - report without certificates
     */
    static async getReportMeasure(report) {
        return (0, amd_sev_snp_napi_rs_1.getReportMeasure)(report);
    }
    static async calculateFileSha256(filePath) {
        const fileData = await fs.readFile(filePath);
        const hash = (0, crypto_1.createHash)("sha256");
        hash.update(fileData);
        return hash.digest();
    }
    static calculateCmdlineHash(cmdLine) {
        const cmdLineBytes = Buffer.concat([Buffer.from(cmdLine.trim(), "utf-8"), Buffer.from([0])]);
        const hash = (0, crypto_1.createHash)("sha256");
        hash.update(cmdLineBytes);
        return hash.digest();
    }
    /**
     * The method allows to get the expected mrEnclave without generating a report
     * @param params - @see CalcSnpMrEnclaveParams
     */
    static async calcSnpMrEnclave(params) {
        const measure = (0, amd_sev_snp_napi_rs_1.calcSnpMeasure)(params.ovmfPath, params.kernelHash, params.initrdHash ?? exports.EMPTY_INITRD_SHA256_HASH, params.cmdLineHash, params.vcpuSig, params.vcpuCount);
        return SevSNP.calcMrEnclave(measure, params.vmpl ?? 0, params.policy ?? BigInt(0x30000));
    }
    static extractBuildFromCmdline(cmdLine, paramName = "build") {
        const regex = new RegExp(`${paramName}=([^\\s]+)`);
        const match = cmdLine.match(regex);
        if (match) {
            return match[1];
        }
        else {
            throw new Error(`${paramName} parameter not found`);
        }
    }
    /**
     * Compute the 32-bit CPUID signature from family, model, and stepping.
     * This computation is described in AMD's CPUID Specification, publication #25481
     * https://www.amd.com/system/files/TechDocs/25481.pdf
     * See section: CPUID Fn0000_0001_EAX Family, Model, Stepping Identifiers
     * @param cpuInfo - Structure containing family, model and stepping @see CpuInfo
     */
    static getCpuSig(cpuInfo) {
        return (0, amd_sev_snp_napi_rs_1.getCpuSig)(cpuInfo);
    }
}
exports.SevSNP = SevSNP;
//# sourceMappingURL=data:application/json;base64, 