c++ - 要求编译器发出无分支/恒定时间代码

标签 c++ c gcc clang secure-coding

在密码学中,任何依赖于 secret 数据(例如私钥)的代码都必须在恒定时间内执行,以避免 side-channel timing attacks .

目前最流行的架构(x86-64 和 ARM AArch64)都支持某些类型的条件执行指令,例如:

即使没有此类说明,也有 techniques to convert a piece of code into a branchless version .性能可能会受到影响,但在这种情况下,这不是主要目标 - 在恒定时间内运行才是。

因此,原则上应该可以编写无分支代码,例如C/C++,事实上,gcc/clang 经常会在打开优化的情况下发出无分支代码(在 gcc 中甚至有一个特定的标志:-fif-conversion2)。然而,这似乎是一个优化决定,如果编译器认为无分支的性能会更差(比如,如果“then”和“else”子句执行大量计算,超过在错误预测的分支),那么我假设编译器将发出常规代码。

如果恒定时间是一个不可协商的目标,则可能会被迫使用上述一些技巧来生成无分支代码,从而使代码不那么清晰。此外,性能通常是次要且非常重要的目标,因此开发人员不得不希望编译器能够推断出无分支代码背后的预期操作,并发出高效的指令序列,通常使用上述指令。这可能需要在查看汇编输出的同时一遍又一遍地重写代码,直到神奇的咒语使编译器满意为止——这可能会随着编译器的不同而改变,或者当新版本出现时。

总的来说,这对双方来说都是一个糟糕的情况:编译器编写者必须从混淆代码中推断出意图,将其转换为更简单的指令序列;而开发人员必须编写此类混淆代码,因为无法保证简单、清晰的代码实际上会在恒定时间内运行。

将其变成一个问题:如果某段代码必须在恒定时间内发出(或根本不发出),是否有编译器标志或编译指示会强制代码这样发出,即使编译器预测性能比分支版本更差,或者如果不可能则中止编译?开发人员将能够安心地编写清晰的代码,因为它将是恒定时间的,同时为编译器提供清晰且易于分析的代码。我知道这可能是一个依赖于语言和编译器的问题,所以我对 gcc 或 clang 的 C 或 C++ 答案感到满意。

最佳答案

我通过类似的兔子洞找到了这个问题。出于安全目的,我要求我的代码不要在 secret 数据上分支,也不要通过定时攻击泄露信息。

虽然这本身不是答案,但我可以推荐这篇来自 S&P 2018 的论文:https://ieeeexplore.ieee.org/document/8406587。 作者还为 CLang/LLVM 编写和扩展。我不确定这个扩展的效果如何,但这是第一步,它很好地概述了我们目前在研究环境中所处的位置。

关于c++ - 要求编译器发出无分支/恒定时间代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68327985/

相关文章:

c++ - 在 Linux 中使用 NONBLOCK 模式的命名管道 + SELECT

c++ - 我们如何在线程中使用参数

c++ - 导入从 pybind11 构建的模块时出现错误 "Segmentation fault (core dumped)"

c++ - type_traits - 连续内存

c - 使用内存映射逐 block 打开和读取大文件 (100GB)

c - 从零开始的标准 C XCode 项目

c++ - 在 GCC 上的 GTEST 中测试失败时是否有打印堆栈跟踪的选项?

c++ - 指向不同派生类的指针数组

c - 使 autotools 添加 --std=c11 到 CFLAGS

c - 使用 RNDADDENTROPY 将熵添加到/dev/random