dit.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 subtle
   6  
   7  import (
   8  	"internal/runtime/sys"
   9  	"runtime"
  10  )
  11  
  12  // WithDataIndependentTiming enables architecture specific features which ensure
  13  // that the timing of specific instructions is independent of their inputs
  14  // before executing f. On f returning it disables these features.
  15  //
  16  // WithDataIndependentTiming should only be used when f is written to make use
  17  // of constant-time operations. WithDataIndependentTiming does not make
  18  // variable-time code constant-time.
  19  //
  20  // WithDataIndependentTiming may lock the current goroutine to the OS thread for
  21  // the duration of f. Calls to WithDataIndependentTiming may be nested.
  22  //
  23  // On Arm64 processors with FEAT_DIT, WithDataIndependentTiming enables
  24  // PSTATE.DIT. See https://developer.arm.com/documentation/ka005181/1-0/?lang=en.
  25  //
  26  // Currently, on all other architectures WithDataIndependentTiming executes f immediately
  27  // with no other side-effects.
  28  //
  29  //go:noinline
  30  func WithDataIndependentTiming(f func()) {
  31  	if !sys.DITSupported {
  32  		f()
  33  		return
  34  	}
  35  
  36  	runtime.LockOSThread()
  37  	defer runtime.UnlockOSThread()
  38  
  39  	alreadyEnabled := sys.EnableDIT()
  40  
  41  	// disableDIT is called in a deferred function so that if f panics we will
  42  	// still disable DIT, in case the panic is recovered further up the stack.
  43  	defer func() {
  44  		if !alreadyEnabled {
  45  			sys.DisableDIT()
  46  		}
  47  	}()
  48  
  49  	f()
  50  }
  51