windows: fix constant value of WTD_STATEACTION_VERIFY

A 0x01 was mistakenly changed to 0x10. This commit rectifies the issue,
while also adding a test to ensure this functionality is behaving as
expected.

Fixes golang/go#46906

Change-Id: I833fe03e69a71283b4f7abb6cf640574d03f5d24
Reviewed-on: https://go-review.googlesource.com/c/sys/+/331010
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/windows/syscall_windows_test.go b/windows/syscall_windows_test.go
index 0aaa0a3..fd75c09 100644
--- a/windows/syscall_windows_test.go
+++ b/windows/syscall_windows_test.go
@@ -624,3 +624,80 @@
 		}
 	}
 }
+
+func TestWinVerifyTrust(t *testing.T) {
+	system32, err := windows.GetSystemDirectory()
+	if err != nil {
+		t.Errorf("unable to find system32 directory: %v", err)
+	}
+	ntoskrnl := filepath.Join(system32, "ntoskrnl.exe")
+	ntoskrnl16, err := windows.UTF16PtrFromString(ntoskrnl)
+	if err != nil {
+		t.Fatalf("unable to get utf16 of ntoskrnl.exe: %v", err)
+	}
+	data := &windows.WinTrustData{
+		Size:             uint32(unsafe.Sizeof(windows.WinTrustData{})),
+		UIChoice:         windows.WTD_UI_NONE,
+		RevocationChecks: windows.WTD_REVOKE_NONE, // No revocation checking, in case the tests don't have network connectivity.
+		UnionChoice:      windows.WTD_CHOICE_FILE,
+		StateAction:      windows.WTD_STATEACTION_VERIFY,
+		FileOrCatalogOrBlobOrSgnrOrCert: unsafe.Pointer(&windows.WinTrustFileInfo{
+			Size:     uint32(unsafe.Sizeof(windows.WinTrustFileInfo{})),
+			FilePath: ntoskrnl16,
+		}),
+	}
+	verifyErr := windows.WinVerifyTrustEx(windows.InvalidHWND, &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2, data)
+	data.StateAction = windows.WTD_STATEACTION_CLOSE
+	closeErr := windows.WinVerifyTrustEx(windows.InvalidHWND, &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2, data)
+	if verifyErr != nil {
+		t.Errorf("ntoskrnl.exe did not verify: %v", verifyErr)
+	}
+	if closeErr != nil {
+		t.Errorf("unable to free verification resources: %v", closeErr)
+	}
+
+	// Now that we've verified legitimate ntoskrnl.exe verifies, let's corrupt it and see if it correctly fails.
+
+	dir, err := ioutil.TempDir("", "go-build")
+	if err != nil {
+		t.Fatalf("failed to create temp directory: %v", err)
+	}
+	defer os.RemoveAll(dir)
+	corruptedNtoskrnl := filepath.Join(dir, "ntoskrnl.exe")
+	ntoskrnlBytes, err := ioutil.ReadFile(ntoskrnl)
+	if err != nil {
+		t.Fatalf("unable to read ntoskrnl.exe bytes: %v", err)
+	}
+	if len(ntoskrnlBytes) > 0 {
+		ntoskrnlBytes[len(ntoskrnlBytes)/2-1]++
+	}
+	err = ioutil.WriteFile(corruptedNtoskrnl, ntoskrnlBytes, 0755)
+	if err != nil {
+		t.Fatalf("unable to write corrupted ntoskrnl.exe bytes: %v", err)
+	}
+	ntoskrnl16, err = windows.UTF16PtrFromString(corruptedNtoskrnl)
+	if err != nil {
+		t.Fatalf("unable to get utf16 of ntoskrnl.exe: %v", err)
+	}
+	data = &windows.WinTrustData{
+		Size:             uint32(unsafe.Sizeof(windows.WinTrustData{})),
+		UIChoice:         windows.WTD_UI_NONE,
+		RevocationChecks: windows.WTD_REVOKE_NONE, // No revocation checking, in case the tests don't have network connectivity.
+		UnionChoice:      windows.WTD_CHOICE_FILE,
+		StateAction:      windows.WTD_STATEACTION_VERIFY,
+		FileOrCatalogOrBlobOrSgnrOrCert: unsafe.Pointer(&windows.WinTrustFileInfo{
+			Size:     uint32(unsafe.Sizeof(windows.WinTrustFileInfo{})),
+			FilePath: ntoskrnl16,
+		}),
+	}
+	verifyErr = windows.WinVerifyTrustEx(windows.InvalidHWND, &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2, data)
+	data.StateAction = windows.WTD_STATEACTION_CLOSE
+	closeErr = windows.WinVerifyTrustEx(windows.InvalidHWND, &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2, data)
+	if verifyErr != windows.Errno(windows.TRUST_E_BAD_DIGEST) {
+		t.Errorf("ntoskrnl.exe did not fail to verify as expected: %v", verifyErr)
+	}
+	if closeErr != nil {
+		t.Errorf("unable to free verification resources: %v", closeErr)
+	}
+
+}
diff --git a/windows/types_windows.go b/windows/types_windows.go
index 1f73339..17f0331 100644
--- a/windows/types_windows.go
+++ b/windows/types_windows.go
@@ -680,7 +680,7 @@
 	WTD_CHOICE_CERT    = 5
 
 	WTD_STATEACTION_IGNORE           = 0x00000000
-	WTD_STATEACTION_VERIFY           = 0x00000010
+	WTD_STATEACTION_VERIFY           = 0x00000001
 	WTD_STATEACTION_CLOSE            = 0x00000002
 	WTD_STATEACTION_AUTO_CACHE       = 0x00000003
 	WTD_STATEACTION_AUTO_CACHE_FLUSH = 0x00000004