// Copyright 2024 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package subtle import ( "internal/runtime/sys" _ "unsafe" ) // WithDataIndependentTiming enables architecture specific features which ensure // that the timing of specific instructions is independent of their inputs // before executing f. On f returning it disables these features. // // Any goroutine spawned by f will also have data independent timing enabled for // its lifetime, as well as any of their descendant goroutines. // // Any C code called via cgo from within f, or from a goroutine spawned by f, will // also have data independent timing enabled for the duration of the call. If the // C code disables data independent timing, it will be re-enabled on return to Go. // // If C code called via cgo, from f or elsewhere, enables or disables data // independent timing then calling into Go will preserve that state for the // duration of the call. // // WithDataIndependentTiming should only be used when f is written to make use // of constant-time operations. WithDataIndependentTiming does not make // variable-time code constant-time. // // Calls to WithDataIndependentTiming may be nested. // // On Arm64 processors with FEAT_DIT, WithDataIndependentTiming enables // PSTATE.DIT. See https://developer.arm.com/documentation/ka005181/1-0/?lang=en. // // Currently, on all other architectures WithDataIndependentTiming executes f immediately // with no other side-effects. // //go:noinline func WithDataIndependentTiming(f func()) { if !sys.DITSupported { f() return } alreadyEnabled := setDITEnabled() // disableDIT is called in a deferred function so that if f panics we will // still disable DIT, in case the panic is recovered further up the stack. defer func() { if !alreadyEnabled { setDITDisabled() } }() f() } //go:linkname setDITEnabled func setDITEnabled() bool //go:linkname setDITDisabled func setDITDisabled()