blob: 733261c3b09d2f99c7d85af19ec812d75bd27f5c [file] [log] [blame] [edit]
// 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()