// run_cavp.go processes CAVP input files and generates suitable response
// files, optionally comparing the results against the provided FAX files.
package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

var (
	binaryDir = flag.String("bin-dir", "", "Directory containing fipsoracle binaries")
)

// test describes a single request file.
type test struct {
	// inFile is the base of the filename without an extension, i.e.
	// “ECBMCT128”.
	inFile string
	// args are the arguments (not including the input filename) to the
	// oracle binary.
	args   []string
	// noFAX, if true, indicates that the output cannot be compared against
	// the FAX file. (E.g. because the primitive is non-deterministic.)
	noFAX bool
}

// testSuite describes a series of tests that are handled by a single oracle
// binary.
type testSuite struct {
	// directory is the name of the directory in the CAVP input, i.e. “AES”.
	directory string
	// binary is the name of the binary that can process these tests.
	binary    string
	tests     []test
}

var aesGCMTests = testSuite{
	"AES_GCM",
	"cavp_aes_gcm_test",
	[]test{
		{"gcmDecrypt128", []string{"dec", "aes-128-gcm"}, false},
		{"gcmDecrypt256", []string{"dec", "aes-256-gcm"}, false},
		{"gcmEncryptIntIV128", []string{"enc", "aes-128-gcm"}, true},
		{"gcmEncryptIntIV256", []string{"enc", "aes-256-gcm"}, true},
	},
}

var aesTests = testSuite{
	"AES",
	"cavp_aes_test",
	[]test{
		{"CBCGFSbox128", []string{"aes-128-cbc"}, false},
		{"CBCGFSbox192", []string{"aes-192-cbc"}, false},
		{"CBCGFSbox256", []string{"aes-256-cbc"}, false},
		{"CBCKeySbox128", []string{"aes-128-cbc"}, false},
		{"CBCKeySbox192", []string{"aes-192-cbc"}, false},
		{"CBCKeySbox256", []string{"aes-256-cbc"}, false},
		{"CBCMMT128", []string{"aes-128-cbc"}, false},
		{"CBCMMT192", []string{"aes-192-cbc"}, false},
		{"CBCMMT256", []string{"aes-256-cbc"}, false},
		{"CBCVarKey128", []string{"aes-128-cbc"}, false},
		{"CBCVarKey192", []string{"aes-192-cbc"}, false},
		{"CBCVarKey256", []string{"aes-256-cbc"}, false},
		{"CBCVarTxt128", []string{"aes-128-cbc"}, false},
		{"CBCVarTxt192", []string{"aes-192-cbc"}, false},
		{"CBCVarTxt256", []string{"aes-256-cbc"}, false},
		{"ECBGFSbox128", []string{"aes-128-ecb"}, false},
		{"ECBGFSbox192", []string{"aes-192-ecb"}, false},
		{"ECBGFSbox256", []string{"aes-256-ecb"}, false},
		{"ECBKeySbox128", []string{"aes-128-ecb"}, false},
		{"ECBKeySbox192", []string{"aes-192-ecb"}, false},
		{"ECBKeySbox256", []string{"aes-256-ecb"}, false},
		{"ECBMMT128", []string{"aes-128-ecb"}, false},
		{"ECBMMT192", []string{"aes-192-ecb"}, false},
		{"ECBMMT256", []string{"aes-256-ecb"}, false},
		{"ECBVarKey128", []string{"aes-128-ecb"}, false},
		{"ECBVarKey192", []string{"aes-192-ecb"}, false},
		{"ECBVarKey256", []string{"aes-256-ecb"}, false},
		{"ECBVarTxt128", []string{"aes-128-ecb"}, false},
		{"ECBVarTxt192", []string{"aes-192-ecb"}, false},
		{"ECBVarTxt256", []string{"aes-256-ecb"}, false},
	},
}

// AES Monte-Carlo tests need a different binary.
//{"ECBMCT128", []string{"aes-128-ecb"}, false},
//{"ECBMCT192", []string{"aes-192-ecb"}, false},
//{"ECBMCT256", []string{"aes-256-ecb"}, false},
//{"CBCMCT128", []string{"aes-128-cbc"}, false},
//{"CBCMCT192", []string{"aes-192-cbc"}, false},
//{"CBCMCT256", []string{"aes-256-cbc"}, false},

var allTestSuites = []*testSuite{
	&aesGCMTests,
	&aesTests,
}

func main() {
	flag.Parse()

	if len(*binaryDir) == 0 {
		fmt.Fprintf(os.Stderr, "Must give -bin-dir\n")
		os.Exit(1)
	}

	for _, suite := range allTestSuites {
		for _, test := range suite.tests {
			if err := doTest(suite, test); err != nil {
				fmt.Fprintf(os.Stderr, "%s\n", err)
				os.Exit(2)
			}

			if !test.noFAX {
				if err := compareFAX(suite, test); err != nil {
					fmt.Fprintf(os.Stderr, "%s\n", err)
					os.Exit(3)
				}
			}
		}
	}
}

func doTest(suite *testSuite, test test) error {
	binary := filepath.Join(*binaryDir, suite.binary)

	var args []string
	args = append(args, test.args...)
	args = append(args, filepath.Join(suite.directory, "req", test.inFile+".req"))

	outPath := filepath.Join(suite.directory, "resp", test.inFile+".resp")
	outFile, err := os.OpenFile(outPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
	if err != nil {
		return fmt.Errorf("cannot open output file for %q %q: %s", suite.directory, test.inFile, err)
	}
	defer outFile.Close()

	cmd := exec.Command(binary, args...)
	cmd.Stdout = outFile
	cmd.Stderr = os.Stderr

	if err := cmd.Run(); err != nil {
		return fmt.Errorf("cannot run command for %q %q: %s", suite.directory, test.inFile, err)
	}

	return nil
}

func compareFAX(suite *testSuite, test test) error {
	respPath := filepath.Join(suite.directory, "resp", test.inFile+".resp")
	respFile, err := os.Open(respPath)
	if err != nil {
		return fmt.Errorf("cannot read output of %q %q: %s", suite.directory, test.inFile, err)
	}
	defer respFile.Close()

	faxPath := filepath.Join(suite.directory, "fax", test.inFile+".fax")
	faxFile, err := os.Open(faxPath)
	if err != nil {
		return fmt.Errorf("cannot open fax file for %q %q: %s", suite.directory, test.inFile, err)
	}
	defer faxFile.Close()

	respScanner := bufio.NewScanner(respFile)
	faxScanner := bufio.NewScanner(faxFile)

	lineNo := 0
	inHeader := true

	for respScanner.Scan() {
		lineNo++
		respLine := respScanner.Text()
		var faxLine string

		if inHeader && (len(respLine) == 0 || respLine[0] == '#') {
			continue
		}

		for {
			haveFaxLine := false

			if inHeader {
				for faxScanner.Scan() {
					faxLine = faxScanner.Text()
					if len(faxLine) != 0 && faxLine[0] != '#' {
						haveFaxLine = true
						break
					}
				}

				inHeader = false
			} else {
				if faxScanner.Scan() {
					faxLine = faxScanner.Text()
					haveFaxLine = true
				}
			}

			if !haveFaxLine {
				return fmt.Errorf("resp file is longer than fax for %q %q", suite.directory, test.inFile)
			}

			if strings.HasPrefix(faxLine, " (Reason: ") {
				continue
			}

			break
		}

		if faxLine == respLine {
			continue
		}

		return fmt.Errorf("resp and fax differ at line %d for %q %q: %q vs %q", lineNo, suite.directory, test.inFile, respLine, faxLine)
	}

	if faxScanner.Scan() {
		return fmt.Errorf("fax file is longer than resp for %q %q", suite.directory, test.inFile)
	}

	return nil
}
