GN⁺: Clang 대 Clang 대결
(blog.cr.yp.to)Clang vs. Clang: Clang을 화나게 하지 마세요
- Clang에 대한 실험을 다룬 블로그 글임
- 컴파일러 최적화와 관련된 최근 LLVM 및 GCC 변경 사항을 살펴보면, 최적화, 최적화 테스트, 테스트 수정, 버그 수정 등이 포함됨
- 컴파일러 작성자들은 자신들이 도입한 버그에 대해 책임을 지지 않으려 함
- 컴파일러 최적화는 실제 성능 향상에 크게 기여하지 않음
컴파일러 최적화의 문제점
- 최적화된 컴파일러가 성능을 향상시키는 경우는 드물음
- 예를 들어, kyber768의 avx2 구현은 최적화된 컴파일러로 컴파일된 코드보다 4배 빠름
- Todd A. Proebsting의 법칙에 따르면, 컴파일러 최적화는 컴퓨팅 성능에 거의 기여하지 않음
- Arseny Kapoulkine의 벤치마크 결과도 비슷한 결론을 내림
보안 문제
- 최적화된 컴파일러는 전통적인 버그뿐만 아니라 타이밍 누출과 같은 보안 문제를 일으킬 수 있음
- 2018년 EuroS&P 논문에 따르면, 컴파일러 업그레이드는 타이밍 채널을 열어 보안 코드를 취약하게 만들 수 있음
- Kyber 참조 코드에서 Clang 15 이상의 최적화 옵션으로 컴파일된 코드에서 성공적인 타이밍 공격이 보고됨
TIMECOP 도구
- TIMECOP 2는 SUPERCOP 암호화 테스트 프레임워크에 내장되어 있으며, 비밀로부터 파생된 조건부 분기를 자동으로 스캔함
- TIMECOP 1과 TIMECOP 2의 차이점: TIMECOP 2는 RNG 출력을 비밀로 자동 표시하고, 다중 코어에서 실행됨
상수 시간 코드 작성
- 상수 시간 코드를 작성하는 방법에 대한 강연을 2024년 7월에 진행함
- libmceliece와 SUPERCOP에서 제공하는 상수 시간 함수 설명
- 예를 들어,
crypto_uint32_bitmod_mask(x,j)
함수는 컴파일러가 1비트 결과를 인식하지 못하게 함
컴파일러 최적화 문제 예방
- 컴파일러가 타이밍 누출을 도입하지 않도록 예방하는 방법 중 하나는 어셈블리 언어로 라이브러리를 배포하는 것임
- 그러나 어셈블리 언어는 소프트웨어의 정확성을 감사하기 어렵게 만들 수 있음
- C, C++ 등의 코드에 타이밍 누출 예방 코드를 빠르게 도입하는 방법을 모색 중임
clang-vs-clang 패치
- LLVM 최적화 도구에 패치를 작성하여
&1
및>>31
을 스캔하고 경고 메시지를 출력함 - 예를 들어,
x >>= 31
코드에서 경고 메시지가 출력됨
결론
- 컴파일러 최적화는 성능 향상에 크게 기여하지 않으며, 보안 문제를 일으킬 수 있음
- TIMECOP과 같은 도구를 사용하여 상수 시간 코드를 작성하고, 컴파일러 최적화 문제를 예방해야 함
GN⁺의 정리
- 이 글은 컴파일러 최적화의 문제점과 보안 위험을 다루고 있음
- 컴파일러 최적화가 실제 성능 향상에 크게 기여하지 않으며, 보안 문제를 일으킬 수 있음을 강조함
- TIMECOP 도구와 상수 시간 코드 작성 방법을 소개하여 보안 문제를 예방하는 방법을 제시함
- 컴파일러 최적화 문제를 예방하기 위해 어셈블리 언어로 라이브러리를 배포하는 방법도 제안함
- 관련 분야의 다른 프로젝트로는 FaCT와 Jasmin 같은 보안 중심의 컴파일러가 있음
Hacker News 의견
-
컴파일러 작성자가 최적화로 인해 발생한 버그에 대해 책임을 지지 않음
- 언어 표준에 따라 이러한 버그는 프로그래머의 잘못으로 간주됨
- 이는 버그가 아니라는 증거임
-
Bernstein의 의견에 동의하지만, 때로는 잘못된 방향으로 나아감
- 최적화의 이점은 사용 사례에 따라 다름
- C 컴파일러가 언어로 표현할 수 없는 의미를 고려하지 않는다는 불만이 있음
- "필요한 의미를 표현할 수 있는 언어를 사용하라"는 결론으로 요약될 수 있음
-
C와 C++는 상수 시간 보장이 필요한 알고리즘 작성에 부적합함
- 표준은 실시간 개념이 거의 없음
- 컴파일러 개발자를 비난하는 것은 잘못된 방향임
-
Intel CPU에서는 clang이나 다른 어떤 것도 사용자 모드에서 올바른 코드를 생성할 수 없음
- DOITM을 설정하는 것은 불가능함
-
컴파일러 작성자가 버그에 대해 책임을 지지 않는다는 주장에 동의하지 않음
- 이는 기본적인 C의 "정의되지 않은 동작"에 대한 오해임
-
clang에는
clang::optnone
속성이 있어 함수별로 최적화를 비활성화할 수 있음- GCC에는
gnu::optimize
속성이 있어 최적화 수준을 설정할 수 있음 -
clang::no_builtins
는 memcpy와 memset 최적화를 비활성화함
- GCC에는
-
C에서 정의되지 않은 동작이 많아 다른 언어로 이동할 가능성이 있음
- Python에서는 set 객체의 순서가 중요하지 않음
- C 컴파일러는 코드 패턴을 분석하여 최적화를 시도함
- 이는 허블 망원경의 문제 해결과 유사한 방식으로 더 나은 성능을 제공할 수 있음
-
암호화 전문가의 목표에 동의하지만, 일반 목적의 컴파일러는 이를 고려하지 않음
- 전문화된 컴파일러가 필요할 수 있음
-
일부 언어와 컴파일러가 상수 시간 암호화 루틴 작성에 부적합하다는 것은 사실임
- 모든 컴파일러와 비어셈블리 언어가 나쁘다는 결론은 잘못됨
- 간단한 도메인 특화 컴파일러와 언어를 작성해야 함
-
특정 함수 예시에서 SIZE_T_MAX 입력 시 정의되지 않은 동작이 발생함
- 이와 같은 버그가 많지만 실제로는 중요하지 않음