TL;DR

  • Go의 FIPS 140 코드가 기본적으로 대부분의 바이너리에 포함되는 문제를 해결하기 위해, 기본 GOFIPS140 값을 disabled로 설정하고 미사용 FIPS 코드의 컴파일을 막자는 제안임.
  • FIPS 140 코드는 기본적으로 비활성화되어도 바이너리에 포함되며, 초기화 함수 실행과 코드 크기 증가, 메모리·디스크·캐시 낭비를 유발한다는 주장임.
  • crypto/rand만 사용하는 간단한 프로그램에도 엔트로피 수집기, AES, DRBG, HMAC, SHA-256·SHA-3·SHA-512 등 광범위한 FIPS 구현이 포함되는 사례임.
  • fips140.Enabled를 변수에서 컴파일 타임 상수로 바꾸고, 일부 파일에 fips140 빌드 태그를 적용해 미사용 코드와 복잡한 의존성을 제거하자는 제안임.
  • 새 기본값은 FIPS 전용 경로를 컴파일에서 제외하며, off, latest, certified, inprocess, 특정 버전 값의 동작은 기존과 동일하게 유지하는 변경임.

개요

  • FIPS 140 코드, 특히 난수 생성기(RNG)는 대다수 Go 바이너리에서 사용되지 않으면서 코드 크기를 불필요하게 늘린다는 주장임.
  • 기술적 관점에서 거의 쓸모없는 코드임에도 이를 실제로 사용하는 일부 사용자를 제외한 대부분은 활성화 절차를 거치지 않으며, 코드는 메모리와 디스크 공간을 차지하고 캐시를 채움.
  • 제안의 핵심은 기본 GOFIPS140=disabled 값을 추가해 사용하지 않는 FIPS 코드를 컴파일하지 않는 것임.

동기

  • 새 FIPS 140 코드는 간접 호출을 늘리고 최종 바이너리의 크기를 크게 키우며, 비활성 상태이거나 사용하지 않는 경우에도 컴파일됨.
  • 사용 여부는 기본적으로 꺼져 있는 GODEBUG 플래그로 제어되지만, 관련 코드는 Go 바이너리에 항상 포함됨.
  • 암호화 코드의 상당 부분을 FIPS 프레임워크로 우회한 뒤 GODEBUG 플래그가 켜지지 않았으면 조기에 빠져나오며, 추가 암호화 코드와 복잡성도 가져옴.
  • 프레임워크를 거치는 간접 호출 외에도 다음 경로에 분기 처리가 추가된다는 주장임.
  • TLS
  • RSA/PKCS1
  • 난수 생성기 래퍼 함수
  • AES/GCM
  • 이러한 미사용 코드는 컴파일 타임 상수로 제어해야 하며, Enabled 심볼도 변수에서 상수로 바꿀 수 있다는 제안임.
  • 특히 난수 생성기 사례를 통해 불필요한 코드 증가를 설명함.
  • crypto/rand를 가져와 1바이트를 읽는 프로그램과 암호화 패키지를 전혀 가져오지 않는 프로그램을 비교하고, go tool objdump 출력의 차이를 확인함.
  • crypto/rand를 사용하면 시스템 호출 등 안전한 난수 바이트 획득에 필요한 일부 내부 암호화 코드가 추가될 것으로 예상할 수 있지만, 실제로는 다음 구성 요소가 포함됨.
  • 사용자 공간 엔트로피 수집기와 해당 수집기를 위한 SHA-384 구현
  • AES 및 AES-NI 가속 AES 구현
  • AES용 CTR 및 GCM 구현
  • 일부 CPU 감지 코드
  • FIPS 지정 DRBG 알고리즘 구현
  • HMAC 구현
  • SHA-256 및 AVX2 가속 SHA-256 구현
  • cSHAKE를 포함한 SHA-3 및 AVX2 가속 SHA-3 구현
  • SHA-512 구현
  • 일반 XOR 바이트 처리 루틴
  • crypto/internal/sysrand와 crypto/rand의 실제 시스템 호출 래퍼
  • 이 구성은 지나치게 방대하며, FIPS 난수 생성 기능이 필요한 사용자가 있더라도 별도 영역에 격리하고 모든 crypto/rand 사용 바이너리에 기본 포함하지 않아야 한다는 주장임.

고려 사항

  • 현재 관련 코드는 GODEBUG로 제어되는 fips140.Enabled 멤버에 따라 동작함.
  • fips140.Enabled를 변수에서 상수로 바꾸면 컴파일러가 미사용 코드를 일반적인 최적화 과정에서 제거할 수 있다는 제안임.
  • 복잡한 의존성 연결 일부는 특정 파일에 fips140 빌드 태그를 적용해 해결할 수 있으며, 이 경우에도 호출은 FIPS 중계 함수를 거치지만 알고리즘과 불필요한 코드는 제거되고 중계 함수 대부분도 인라인 처리될 수 있음.
  • FiloSottile과 비공식적으로 논의하는 과정에서 테스트와 지속적 통합(CI)에 대한 우려가 제기됨.
  • 이에 따라 필요한 부분을 다시 컴파일하도록 테스트를 재구성해야 하며, 현재 변경 목록(CL) 묶음은 이를 유지 관리 부담을 줄이는 방식으로 자동화함.

제안

  • 새 기본 GOFIPS140=disabled 값은 난수 생성기와 추가 분기 등 FIPS 전용 경로를 바이너리에 컴파일하지 않는 동작임.
  • GOFIPS140 값별 변경 전후 동작은 다음과 같음.
  • 값 미설정: 변경 전 기본값은 off, 변경 후 기본값은 disabled
  • disabled: 변경 전에는 유효하지 않은 값, 변경 후에는 FIPS 모드를 사용할 수 없고 fips140.Enabled가 컴파일 타임 상수 false임
  • off: FIPS 지원 코드를 포함하되 시작 시 비활성화하는 동작으로 변경 없음
  • latest: 현재 모듈을 사용하고 기본 활성화하는 동작으로 변경 없음
  • certified: 인증된 스냅샷을 사용하고 기본 활성화하는 동작으로 변경 없음
  • inprocess: 인증 절차 진행 중인 스냅샷을 사용하고 기본 활성화하는 동작으로 변경 없음
  • 지원 버전 지정: 지정된 스냅샷을 사용하고 기본 활성화하는 동작으로 변경 없음

구현