summaryrefslogtreecommitdiff
path: root/src/verify_test.go
blob: fc78ec3286174ede370a802580583f233dcb2437 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package eduvpn

import (
	"bufio"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"testing"
)

func Test_verifyWithKeys(t *testing.T) {
	var err error

	var pk []string
	{
		file, err := os.Open("test_data/public.key")
		if err != nil {
			panic(err)
		}
		defer file.Close()

		// Get last line (key string) from file
		scanner := bufio.NewScanner(file)
		for i := 0; i < 2; i++ {
			if !scanner.Scan() {
				panic(scanner.Err())
			}
		}
		pk = []string{scanner.Text()}
	}

	var (
		verifyCreatePublicKeyError           *VerifyCreatePublicKeyError
		verifyInvalidSignatureAlgorithmError *VerifyInvalidSignatureAlgorithmError
		verifyWrongSigFilenameError          *VerifyWrongSigFilenameError
		verifyInvalidTrustedCommentError     *VerifyInvalidTrustedCommentError
		verifyInvalidSignatureFormatError    *VerifyInvalidSignatureFormatError
		verifyInvalidSignatureError          *VerifyInvalidSignatureError
		verifySigTimeEarlierError            *VerifySigTimeEarlierError
		verifyUnknownExpectedFilenameError   *VerifyUnknownExpectedFilenameError
		verifyUnknownKeyError                *VerifyUnknownKeyError
	)

	tests := []struct {
		expectedErr      interface{}
		testName         string
		signatureFile    string
		jsonFile         string
		expectedFileName string
		minSignTime      uint64
		allowedPks       []string
	}{
		{&verifyInvalidSignatureAlgorithmError, "pure", "server_list.json.pure.minisig", "server_list.json", "server_list.json", 10, pk},

		{nil, "valid server_list", "server_list.json.minisig", "server_list.json", "server_list.json", 10, pk},
		{nil, "TC no hashed", "server_list.json.tc_nohashed.minisig", "server_list.json", "server_list.json", 10, pk},
		{nil, "TC later time", "server_list.json.tc_latertime.minisig", "server_list.json", "server_list.json", 10, pk},
		{&verifyWrongSigFilenameError, "server_list TC file:organization_list", "server_list.json.tc_orglist.minisig", "server_list.json", "server_list.json", 10, pk},
		{&verifyWrongSigFilenameError, "organization_list as server_list", "organization_list.json.minisig", "organization_list.json", "server_list.json", 10, pk},
		{&verifyWrongSigFilenameError, "TC file:otherfile", "server_list.json.tc_otherfile.minisig", "server_list.json", "server_list.json", 10, pk},
		{&verifySigTimeEarlierError, "TC no file", "server_list.json.tc_nofile.minisig", "server_list.json", "server_list.json", 10, pk},
		{&verifySigTimeEarlierError, "TC no time", "server_list.json.tc_notime.minisig", "server_list.json", "server_list.json", 10, pk},
		{&verifySigTimeEarlierError, "TC empty time", "server_list.json.tc_emptytime.minisig", "server_list.json", "server_list.json", 10, pk},
		{&verifyInvalidSignatureFormatError, "TC empty file", "server_list.json.tc_emptyfile.minisig", "server_list.json", "server_list.json", 10, pk},
		{&verifyInvalidTrustedCommentError, "TC random", "server_list.json.tc_random.minisig", "server_list.json", "server_list.json", 10, pk},
		{nil, "large time", "server_list.json.large_time.minisig", "server_list.json", "server_list.json", 43e8, pk},
		{nil, "lower min time", "server_list.json.minisig", "server_list.json", "server_list.json", 5, pk},
		{&verifySigTimeEarlierError, "higher min time", "server_list.json.minisig", "server_list.json", "server_list.json", 11, pk},

		{nil, "valid organization_list", "organization_list.json.minisig", "organization_list.json", "organization_list.json", 10, pk},
		{&verifyWrongSigFilenameError, "organization_list TC file:server_list", "organization_list.json.tc_servlist.minisig", "organization_list.json", "organization_list.json", 10, pk},
		{&verifyWrongSigFilenameError, "server_list as organization_list", "server_list.json.minisig", "server_list.json", "organization_list.json", 10, pk},

		{&verifyUnknownExpectedFilenameError, "valid other_list", "other_list.json.minisig", "other_list.json", "other_list.json", 10, pk},
		{&verifyWrongSigFilenameError, "other_list as server_list", "other_list.json.minisig", "other_list.json", "server_list.json", 10, pk},

		{&verifyInvalidSignatureFormatError, "invalid signature file", "random.txt", "server_list.json", "server_list.json", 10, pk},
		{&verifyInvalidSignatureFormatError, "empty signature file", "empty", "server_list.json", "server_list.json", 10, pk},

		{&verifyUnknownKeyError, "wrong key", "server_list.json.wrong_key.minisig", "server_list.json", "server_list.json", 10, pk},

		{&verifyInvalidSignatureAlgorithmError, "forged pure signature", "server_list.json.forged_pure.minisig", "server_list.json.blake2b", "server_list.json", 10, pk},
		{&verifyInvalidSignatureError, "forged key ID", "server_list.json.forged_keyid.minisig", "server_list.json", "server_list.json", 10, pk},

		{&verifyUnknownKeyError, "no allowed keys", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{}},
		{nil, "multiple allowed keys 1", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{
			pk[0], "RWSf0PYToIUJmDlsz21YOXvgQzHj9NSdyJUqEY5ZdfS9GepeXt3+JJRZ",
		}},
		{nil, "multiple allowed keys 2", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{
			"RWSf0PYToIUJmDlsz21YOXvgQzHj9NSdyJUqEY5ZdfS9GepeXt3+JJRZ", pk[0],
		}},
		{&verifyCreatePublicKeyError, "invalid allowed key", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{"AAA"}},
	}

	// Cache file contents in map, mapping file names to contents
	files := map[string][]byte{}
	loadFile := func(name string) {
		content, loaded := files[name]
		if !loaded {
			content, err = ioutil.ReadFile("test_data/" + name)
			if err != nil {
				panic(err)
			}
			files[name] = content
		}
	}
	for _, test := range tests {
		loadFile(test.signatureFile)
		loadFile(test.jsonFile)
	}

	forcePrehash := true
	for _, tt := range tests {
		t.Run(tt.testName, func(t *testing.T) {
			t.Parallel()
			valid, err := verifyWithKeys(string(files[tt.signatureFile]), files[tt.jsonFile],
				tt.expectedFileName, tt.minSignTime, tt.allowedPks, forcePrehash)
			compareResults(t, valid, err, tt.expectedErr, func() string {
				return fmt.Sprintf("verifyWithKeys(%q, %q, %q, %v, %v, %t)",
					tt.signatureFile, tt.jsonFile, tt.expectedFileName, tt.minSignTime, tt.allowedPks, forcePrehash)
			})
		})
	}
}

// compareResults compares returned ret, err from a verify function with expected error code expected.
// callStr is called to get the formatted parameters passed to the function.
func compareResults(t *testing.T, ret bool, err error, expectedErr interface{}, callStr func() string) {
	// different error returned
	if expectedErr != nil && !errors.As(err, expectedErr) {
		t.Errorf("%v\nerror %T = %v, wantErr %T", callStr(), err, err, expectedErr)
		return
	}
	// different boolean returned
	expectedBool := expectedErr == nil
	if ret != expectedBool {
		t.Errorf("%v\n= %v, want %v", callStr(), ret, expectedBool)
	}
}