indicator.mx raw

   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