1 // Copyright 2024 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 package fips140
6 7 import _ "unsafe" // for go:linkname
8 9 // The service indicator lets users of the module query whether invoked services
10 // are approved. Three states are stored in a per-goroutine value by the
11 // runtime. The indicator starts at indicatorUnset after a reset. Invoking an
12 // approved service transitions to indicatorTrue. Invoking a non-approved
13 // service transitions to indicatorFalse, and it can't leave that state until a
14 // reset. The idea is that functions can "delegate" checks to inner functions,
15 // and if there's anything non-approved in the stack, the final result is
16 // negative. Finally, we expose indicatorUnset as negative to the user, so that
17 // we don't need to explicitly annotate fully non-approved services.
18 19 //go:linkname getIndicator crypto/internal/fips140.getIndicator
20 func getIndicator() uint8
21 22 //go:linkname setIndicator crypto/internal/fips140.setIndicator
23 func setIndicator(uint8)
24 25 const (
26 indicatorUnset uint8 = iota
27 indicatorFalse
28 indicatorTrue
29 )
30 31 // ResetServiceIndicator clears the service indicator for the running goroutine.
32 func ResetServiceIndicator() {
33 setIndicator(indicatorUnset)
34 }
35 36 // ServiceIndicator returns true if and only if all services invoked by this
37 // goroutine since the last ResetServiceIndicator call are approved.
38 //
39 // If ResetServiceIndicator was not called before by this goroutine, its return
40 // value is undefined.
41 func ServiceIndicator() bool {
42 return getIndicator() == indicatorTrue
43 }
44 45 // RecordApproved is an internal function that records the use of an approved
46 // service. It does not override RecordNonApproved calls in the same span.
47 //
48 // It should be called by exposed functions that perform a whole cryptographic
49 // alrgorithm (e.g. by Sum, not by New, unless a cryptographic Instantiate
50 // algorithm is performed) and should be called after any checks that may cause
51 // the function to error out or panic.
52 func RecordApproved() {
53 if getIndicator() == indicatorUnset {
54 setIndicator(indicatorTrue)
55 }
56 }
57 58 // RecordNonApproved is an internal function that records the use of a
59 // non-approved service. It overrides any RecordApproved calls in the same span.
60 func RecordNonApproved() {
61 setIndicator(indicatorFalse)
62 }
63