[Linux] 檢查 OpenSSL 是否掛載了 FIPS 模組
最近專案被要求支援 FIPS (Federal Information Processing Standards) 140-2~
什麼是 FIPS 140-2呢?
基本上就是美國政府公認過、安全可用的演算法的集合,
所以有許多有規模的公司,也會要求採買的產品是符合這個規範的。
平常加解密常用的 OpenSSL,可以在加上一個 FIPS 模組之後,
限制那些不在 FIPS 允許清單內的功能,
像是 MD5 就會被禁止使用,
一呼叫到 MD5 相關的函式,就會吐出錯誤訊息之後 abort()…
而 MD5 還只是不被允許使用的眾多演算法之一…
麻煩的是,MD5 除了直接計算某個檔案內容的雜湊值外,
還可能用在其他地方,連帶使這些東西都不能用。
例如我們本來會支援 HTTP Proxy 中的 Basic、Digest 和 NTLM 等不同的驗證方式,
但因為 Digest/NTLM 這兩種驗證方式裡面都會用到 MD5,
所以它們就變成不能使用了!
不能用就算了,curl 在經由 Digest/NTLM proxy 時還會因此當掉,
這才是最糟糕的地方…
總不能跟客戶說,因為 FIPS 不允許 MD5,
所以我們的程式在這種情況下會當機 Orz…
現在找到的一個解法,是設定 CURLOPT_HTTPAUTH 這個選項,
把平常常用的 CURLAUTH_ANY 換成 CURLAUTH_BASIC,
這樣 curl 就不會去支援 Digest/NTLM,自然就不會去用到 OpenSSL MD5 函式而當機了~
proxy_auth = pycurl.HTTPAUTH_ANY # When FIPS mode is enabled, http proxy only allow basic authentication if is_fips_mode_enabled(): proxy_auth = pycurl.HTTPAUTH_BASIC # FIPS mode is disabled, NTLM can be used elif is_ntlm: proxy_auth = pycurl.HTTPAUTH_NTLM self._curl.setopt(pycurl.PROXYAUTH, proxy_auth)
至於要怎麼檢查現在是 FIPS 模式呢?
網路上有些作法是檢查系統設定:
cat /proc/sys/crypto/fips_enabled sysctl crypto.fips_enabled
但以上的作法看起來是在 Linux Kernel 開啟 FIPS 模式才會有效,
像我們只是套用了 OpenSSL 的 FIPS 模組的話,
上面的設定都是 0,檢查不出 FIPS 有開啟…
後來發現最簡單的方式, 就是直接去執行 MD5 相關的東西,
會掛掉就是 FIPS 模式了~
像是執行這段指令來試著產生 hashlib.md5() 物件,
但如果 OpenSSL FIPS 模組有掛上的話,就會跑出 exception:
python -c 'import hashlib; hashlib.md5()'
只要檢查 python 最後的 exit code 是否為 0,
0 的話表示現在不是 FIPS 模式,
非 0 值表示程式當掉,也就是 FIPS 有開囉~
另外一種方式是比較正規的,
就是去查詢 libcrypto 提供的 FIPS_mode() 函式,
回傳值如果是 1 就是有開 FIPS 模式囉:
import ctypes libcrypto = ctypes.CDLL("libcrypto.so") get_fips_mode = libcrypto.FIPS_mode get_fips_mode.argtypes = [] get_fips_mode.restype = ctypes.c_int fips_mode = get_fips_mode()
參考資料:
curl: Disable accepting MD5 certificates
stackoverflow: How to check FIPS 140-2 support in OpenSSL?