// Copyright 2016 The BoringSSL 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
//
//     https://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.

//go:build ignore

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math/big"
	"os"
	"slices"
	"strings"
)

type test struct {
	LineNumber int
	Type       string
	Values     map[string]*big.Int
}

type testScanner struct {
	scanner *bufio.Scanner
	lineNo  int
	err     error
	test    test
}

func newTestScanner(r io.Reader) *testScanner {
	return &testScanner{scanner: bufio.NewScanner(r)}
}

func (s *testScanner) scanLine() bool {
	if !s.scanner.Scan() {
		return false
	}
	s.lineNo++
	return true
}

func (s *testScanner) addAttribute(line string) (key string, ok bool) {
	fields := strings.SplitN(line, "=", 2)
	if len(fields) != 2 {
		s.setError(errors.New("invalid syntax"))
		return "", false
	}

	key = strings.TrimSpace(fields[0])
	value := strings.TrimSpace(fields[1])

	valueInt, ok := new(big.Int).SetString(value, 16)
	if !ok {
		s.setError(fmt.Errorf("could not parse %q", value))
		return "", false
	}
	if _, dup := s.test.Values[key]; dup {
		s.setError(fmt.Errorf("duplicate key %q", key))
		return "", false
	}
	s.test.Values[key] = valueInt
	return key, true
}

func (s *testScanner) Scan() bool {
	s.test = test{
		Values: make(map[string]*big.Int),
	}

	// Scan until the first attribute.
	for {
		if !s.scanLine() {
			return false
		}
		if len(s.scanner.Text()) != 0 && s.scanner.Text()[0] != '#' {
			break
		}
	}

	var ok bool
	s.test.Type, ok = s.addAttribute(s.scanner.Text())
	if !ok {
		return false
	}
	s.test.LineNumber = s.lineNo

	for s.scanLine() {
		if len(s.scanner.Text()) == 0 {
			break
		}

		if s.scanner.Text()[0] == '#' {
			continue
		}

		if _, ok := s.addAttribute(s.scanner.Text()); !ok {
			return false
		}
	}
	return s.scanner.Err() == nil
}

func (s *testScanner) Test() test {
	return s.test
}

func (s *testScanner) Err() error {
	if s.err != nil {
		return s.err
	}
	return s.scanner.Err()
}

func (s *testScanner) setError(err error) {
	s.err = fmt.Errorf("line %d: %s", s.lineNo, err)
}

func checkKeys(t test, keys ...string) bool {
	var foundErrors bool

	for _, k := range keys {
		if _, ok := t.Values[k]; !ok {
			fmt.Fprintf(os.Stderr, "Line %d: missing key %q.\n", t.LineNumber, k)
			foundErrors = true
		}
	}

	for k := range t.Values {
		if !slices.Contains(keys, k) {
			fmt.Fprintf(os.Stderr, "Line %d: unexpected key %q.\n", t.LineNumber, k)
			foundErrors = true
		}
	}

	return !foundErrors
}

func checkResult(t test, expr, key string, r *big.Int) {
	if t.Values[key].Cmp(r) != 0 {
		fmt.Fprintf(os.Stderr, "Line %d: %s did not match %s.\n\tGot %s\n", t.LineNumber, expr, key, r.Text(16))
	}
}

func main() {
	if len(os.Args) != 2 {
		fmt.Fprintf(os.Stderr, "Usage: %s bn_tests.txt\n", os.Args[0])
		os.Exit(1)
	}

	in, err := os.Open(os.Args[1])
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error opening %s: %s.\n", os.Args[0], err)
		os.Exit(1)
	}
	defer in.Close()

	scanner := newTestScanner(in)
	for scanner.Scan() {
		test := scanner.Test()
		switch test.Type {
		case "Sum":
			if checkKeys(test, "A", "B", "Sum") {
				r := new(big.Int).Add(test.Values["A"], test.Values["B"])
				checkResult(test, "A + B", "Sum", r)
			}
		case "LShift1":
			if checkKeys(test, "A", "LShift1") {
				r := new(big.Int).Add(test.Values["A"], test.Values["A"])
				checkResult(test, "A + A", "LShift1", r)
			}
		case "LShift":
			if checkKeys(test, "A", "N", "LShift") {
				r := new(big.Int).Lsh(test.Values["A"], uint(test.Values["N"].Uint64()))
				checkResult(test, "A << N", "LShift", r)
			}
		case "RShift":
			if checkKeys(test, "A", "N", "RShift") {
				r := new(big.Int).Rsh(test.Values["A"], uint(test.Values["N"].Uint64()))
				checkResult(test, "A >> N", "RShift", r)
			}
		case "Square":
			if checkKeys(test, "A", "Square") {
				r := new(big.Int).Mul(test.Values["A"], test.Values["A"])
				checkResult(test, "A * A", "Square", r)
			}
		case "Product":
			if checkKeys(test, "A", "B", "Product") {
				r := new(big.Int).Mul(test.Values["A"], test.Values["B"])
				checkResult(test, "A * B", "Product", r)
			}
		case "Quotient":
			if checkKeys(test, "A", "B", "Quotient", "Remainder") {
				q, r := new(big.Int).QuoRem(test.Values["A"], test.Values["B"], new(big.Int))
				checkResult(test, "A / B", "Quotient", q)
				checkResult(test, "A % B", "Remainder", r)
			}
		case "ModMul":
			if checkKeys(test, "A", "B", "M", "ModMul") {
				r := new(big.Int).Mul(test.Values["A"], test.Values["B"])
				r = r.Mod(r, test.Values["M"])
				checkResult(test, "A * B (mod M)", "ModMul", r)
			}
		case "ModExp":
			if checkKeys(test, "A", "E", "M", "ModExp") {
				r := new(big.Int).Exp(test.Values["A"], test.Values["E"], test.Values["M"])
				checkResult(test, "A ^ E (mod M)", "ModExp", r)
			}
		case "Exp":
			if checkKeys(test, "A", "E", "Exp") {
				r := new(big.Int).Exp(test.Values["A"], test.Values["E"], nil)
				checkResult(test, "A ^ E", "Exp", r)
			}
		case "ModSqrt":
			bigOne := big.NewInt(1)
			bigTwo := big.NewInt(2)

			if checkKeys(test, "A", "P", "ModSqrt") {
				test.Values["A"].Mod(test.Values["A"], test.Values["P"])

				r := new(big.Int).Mul(test.Values["ModSqrt"], test.Values["ModSqrt"])
				r = r.Mod(r, test.Values["P"])
				checkResult(test, "ModSqrt ^ 2 (mod P)", "A", r)

				if test.Values["P"].Cmp(bigTwo) > 0 {
					pMinus1Over2 := new(big.Int).Sub(test.Values["P"], bigOne)
					pMinus1Over2.Rsh(pMinus1Over2, 1)

					if test.Values["ModSqrt"].Cmp(pMinus1Over2) > 0 {
						fmt.Fprintf(os.Stderr, "Line %d: ModSqrt should be minimal.\n", test.LineNumber)
					}
				}
			}
		case "ModInv":
			if checkKeys(test, "A", "M", "ModInv") {
				a := test.Values["A"]
				m := test.Values["M"]
				var r *big.Int
				if a.Sign() == 0 && m.IsInt64() && m.Int64() == 1 {
					// OpenSSL says 0^(-1) mod (1) is 0, while Go says the
					// inverse does not exist.
					r = big.NewInt(0)
				} else {
					r = new(big.Int).ModInverse(a, m)
				}
				if r == nil {
					fmt.Fprintf(os.Stderr, "Line %d: A has no inverse mod M.\n", test.LineNumber)
				} else {
					checkResult(test, "A ^ -1 (mod M)", "ModInv", r)
				}
			}
		case "ModSquare":
			if checkKeys(test, "A", "M", "ModSquare") {
				r := new(big.Int).Mul(test.Values["A"], test.Values["A"])
				r = r.Mod(r, test.Values["M"])
				checkResult(test, "A * A (mod M)", "ModSquare", r)
			}
		case "NotModSquare":
			if checkKeys(test, "P", "NotModSquare") {
				if new(big.Int).ModSqrt(test.Values["NotModSquare"], test.Values["P"]) != nil {
					fmt.Fprintf(os.Stderr, "Line %d: value was a square.\n", test.LineNumber)
				}
			}
		case "GCD":
			if checkKeys(test, "A", "B", "GCD", "LCM") {
				a := test.Values["A"]
				b := test.Values["B"]
				// Go's GCD function does not accept zero, unlike OpenSSL.
				var g *big.Int
				if a.Sign() == 0 {
					g = b
				} else if b.Sign() == 0 {
					g = a
				} else {
					g = new(big.Int).GCD(nil, nil, a, b)
				}
				checkResult(test, "GCD(A, B)", "GCD", g)
				if g.Sign() != 0 {
					lcm := new(big.Int).Mul(a, b)
					lcm = lcm.Div(lcm, g)
					checkResult(test, "LCM(A, B)", "LCM", lcm)
				}
			}
		default:
			fmt.Fprintf(os.Stderr, "Line %d: unknown test type %q.\n", test.LineNumber, test.Type)
		}
	}
	if scanner.Err() != nil {
		fmt.Fprintf(os.Stderr, "Error reading tests: %s.\n", scanner.Err())
	}
}
