// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

// capture_hash runs another executable that has been linked with libcrypto. It expects the libcrypto to run the
// power-on self-tests and fail due to a fingerprint mismatch. capture_hash parses the output, takes the correct
// fingerprint value, and generates a new C file that contains the correct fingerprint which is used to build the
// final libcrypto.

package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"strings"
)

const line0 = "AWS-LC FIPS failure caused by:"
const line1 = "FIPS integrity test failed."

// This must match what is in crypto/fipsmodule/fips_shared_support.c
const line2 = "Expected:   ae2cea2abda6f3ec977f9bf6949afc836827cba0a09f6b6fde52cde2cdff3180"
const hash_len = 64
func main() {
	executable := flag.String("in-executable", "", "Path to the executable file")
	flag.Parse()
	cmd := exec.Command(*executable)
	out, err := cmd.CombinedOutput()
	if err == nil {
		fmt.Fprintf(os.Stderr, string(out))
		panic("Executable did not fail as expected")
	}
	lines := strings.Split(string(out), "\r\n")
	if len(lines) != 6 {
		fmt.Fprintf(os.Stderr, string(out))
		panic(fmt.Sprintf("Expected 6 lines in output but got %d", len(lines)))
	}

	if lines[0] != line0 {
		fmt.Fprintf(os.Stderr, string(out))
		panic(fmt.Sprintf("Expected \"%s\" got \"%s\"", line0, lines[0]))
	}

	if lines[1] != line1 {
		fmt.Fprintf(os.Stderr, string(out))
		panic(fmt.Sprintf("Expected \"%s\" got \"%s\"", line1, lines[1]))
	}
	if lines[2] != line2 {
		fmt.Fprintf(os.Stderr, string(out))
		panic(fmt.Sprintf("Expected \"%s\" got \"%s\"", line1, lines[1]))
	}
	hash := strings.Split(lines[3], " ")[1]

	if len(hash) != hash_len {
		fmt.Fprintf(os.Stderr, string(out))
		panic(fmt.Sprintf("Hash \"%s\" is %d long, expected %d", hash, len(hash), hash_len))
	}

	fmt.Printf(`// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC
// This file is generated by: 'go run util/fipstools/capture_hash/capture_hash.go -in-executable %s'
#include <stdint.h>
const uint8_t BORINGSSL_bcm_text_hash[32] = {
`, *executable)
	for i:= 0; i < len(hash); i+=2 {
		fmt.Printf("0x%s, ", hash[i:i+2])
	}
	fmt.Printf(`
};
`)
}