aarch64-dit crate is missing fencing (for both compiler and CPU)
维护者通常 2 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 35/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- rust
- 领域
- cryptography, security
调研方向
首先检查 aarch64-dit crate 和链接的 Godbolt 示例,以验证编译器重排序可能会将敏感操作移到 DIT 区域之外。审阅链接的 Apple 指南以及针对推测执行屏障和 cpufeatures 支持的拟议比较补丁。完成的标准是正确阻止编译器和 CPU 的推测执行,并解决 enable API 及其安全性影响。
由索引模型根据 Issue 内容生成。
描述
The aarch64-dit crate has two notable flaws:
- It is possible for the compiler to reorder operations outside the critical section where DIT is enabled.
- It does not perform speculation fencing, which is documented as necessary at least on apple platforms in this document: https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Enable-DIT-for-constant-time-cryptographic-operations.
Flaw 1: Compiler Reordering
Here's an example of the first flaw: https://godbolt.org/z/8fdsnxrc5. Essentially the compiler is free to move instructions outside of the asm!("msr DIT #1") and asm!("msr DIT #0") guarded region, and you can see that it essentially compiles:
if have_dit {
dit_enable();
}
let res = sensitive(a, b);
if have_dit {
dit_disable();
}
return res;
into
if have_dit {
dit_enable();
dit_disable();
}
return sensitive(a, b);
which defeats the point, since the instructions which are data-dependent are no longer in the block where DIT is enabled.
In an ideal world, inserting compiler fences (or atomic fences, or adjusting the asm! options...) would fix this, however they only apply to memory accesses, so that does not work. The only approach I can think of that does work is to use an indirect jump whose target we obscure from the vision of the compiler. Something like:
impl Dit {
// ...snip ...
/// Call `f` with DIT enabled, returning the result. Takes care to ensure
/// that that any computations which occur during `f` do not leak outside
/// the critical section.
pub fn with<R, F: FnOnce() -> R>(s: &self, f: F) -> R {
let guard = self.enable();
let mut o: Option<F> = Some(f);
// Note: Could be unwrap_unchecked().
let f: &mut dyn FnMut() -> R = &mut || o.take().unwrap()();
core::hint::black_box(f)()
}
// ...snip...
}
This works, as demonstrated here: https://godbolt.org/z/fv1Gofjxc (note: the add instruction was changed to floating point addition just so that it's clearer in the assembly listing what is happening—you can see that the fadd takes place in the indirectly called function, which is called (the blr x8) between the msr DIT #1; and msr DIT #0 instructions.
Flaw 2: Speculation
I'm unsure if this is needed on targets besides apple (my suspicion is yes, or at least that there's no guarantee for it to be a no), but apple documents it as necessary in the linked documentation.
Essentially, you need something like this after you enable DIT, and before you disable it (actually, I think you might not need it before disabling it, since it's fine if a DIT-mode processor speculates operations outside of DIT mode).
if is_aarch64_feature_detected!("sb") {
// note: in the real impl this must happen
// in a `#[target_feature(enable = "sb")]` function)
asm!("sb");
} else {
asm!("dsb nsh", "isb sy");
}
Of course, a real impl needs to:
- Put
asm!("sb")inside a#[target_feature(enable = "sb")]function. - Use
cpufeaturesrather thanis_aarch64_feature_detected(which requires addingsbsupport tocpufeatures). - And so on.
A patch fixing these issues is here: https://github.com/RustCrypto/utils/compare/master...thomcc:rust-crypto-utils:aarch64-dit-sb-fix. I don't have time to do a PR and respond to review feedback, feel free to mess with it however you please, or to take a different approach that solves the same problem.
One issue with my patch is that it leaves the Dit::enable() function present and non-deprecated, even though it's a footgun. I think probably the right call would be to remove it. But that begs the question of whether or not the API should have a different structure in other ways too.
- 主要语言
- Rust
- 星标
- 674
- 派生
- 170
- 平均合并
- 1 天 12 小时
- 30 天内合并 PR
- 10
环境准备
我们还没有检查这个项目的环境配置文件。先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
RustCrypto/utils 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 75/100
RustCrypto/utils#1546 · 1 条评论 ·
维护者通常 2 天内回复
-
难度 3/5 1-2 天 新手友好度 55/100
RustCrypto/utils#1537 · 7 条评论 ·
维护者通常 2 天内回复
-
难度 4/5 3-5 天 新手友好度 45/100
RustCrypto/utils#1534 · 2 条评论 ·
维护者通常 2 天内回复
-
难度 5/5 一周以上 新手友好度 45/100
RustCrypto/utils#1529 · 4 条评论 ·
维护者通常 2 天内回复
-
难度 4/5 3-5 天 新手友好度 45/100
RustCrypto/utils#1510 · 1 条评论 ·
维护者通常 2 天内回复
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 74/100
arkworks-rs/algebra#1161 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 85/100
lbjlaq/Antigravity-Manager#3525 · 2 条评论 · 1 个 reaction ·
维护者通常 1 天内回复
-
agent-ready area:platform bug criticality:p3 rust triage:needs-implementation
难度 2/5 1-3 小时 新手友好度 88/100
registrystack/registry-stack#1583 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 74/100
维护者通常 1 天内回复
-
app documentation remote windows-os
难度 1/5 1-3 小时 新手友好度 88/100
维护者通常 1 天内回复