  Progress has recently been made on specifying instruction set architectures
(ISAs) in executable formalisms rather than through prose. However, to date,
those formal specifications are limited to the functional aspects of the ISA
and do not cover its security guarantees. We present a novel, general method
for formally specifying an ISAs security guarantees to (1) balance the needs of
ISA implementations (hardware) and clients (software), (2) can be
semi-automatically verified to hold for the ISA operational semantics,
producing a high-assurance mechanically-verifiable proof, and (3) support
informal and formal reasoning about security-critical software in the presence
of adversarial code. Our method leverages universal contracts: software
contracts that express bounds on the authority of arbitrary untrusted code.
Universal contracts can be kept agnostic of software abstractions, and strike
the right balance between requiring sufficient detail for reasoning about
software and preserving implementation freedom of ISA designers and CPU
implementers. We semi-automatically verify universal contracts against Sail
implementations of ISA semantics using our Katamaran tool; a semi-automatic
separation logic verifier for Sail which produces machine-checked proofs for
successfully verified contracts. We demonstrate the generality of our method by
applying it to two ISAs that offer very different security primitives: (1)
MinimalCaps: a custom-built capability machine ISA and (2) a (somewhat
simplified) version of RISC-V with PMP. We verify a femtokernel using the
security guarantee we have formalized for RISC-V with PMP.
