OpenSSL支援TLS1.3特性前瞻

hdgara1發表於2020-03-03

OpenSSL支援TLS1.3特性前瞻

本文由Matt Caswell於2015年5月4日釋出在OpenSSL部落格。

即將到來的OpenSSL 1.1.1版本將支援TLS 1.3。這個新版本將相容OpenSSL 1.1.0版本的二進位制檔案和API。理論上,如果你的應用程式支援OpenSSL 1.1.0,那麼當更新可用時,TLS 1.3版本也將自動得到支援,你不需要專門進行安裝。但有一些問題仍需要應用程式開發人員和部署人員瞭解。在這篇部落格中,我將談談其中的一些問題。

與TLS 1.2及更早版本的區別

TLS 1.3版本是對規範的重大修改。它到底應該叫TLS 2.0還是現在的名字TLS 1.3,還存在一些爭論。該版本有重大變化,一些工作方式也非常不同。下面是你可能需要注意的一些問題,簡明扼要,不過並不太全面。

  • 有一些新的密碼套件僅在TLS 1.3下工作。一些舊的密碼套件無法用於TLS 1.3連線。
  • 新的密碼套件定義方式不同,且並未詳細規定證書型別(如RSA、DSA、ECDSA)或金鑰交換機制(如DHE或ECHDE)。這對密碼套件的配置有暗示作用。
  • 客戶端在客戶問候訊息(ClientHello)中提供一個“key_share”。這會對“組”配置產生影響。
  • 直到主握手完成以後,會話才會建立。在握手結束和會話建立之間可能會有一個間隙(理論上,會話可能根本不會建立),並可能對會話恢復程式碼產生影響。
  • 在TLS 1.3版本中,重新磋商是不可能的。
  • 現在大部分握手都會被加密。
  • 更多型別的訊息現在可以有擴充套件(這對定製擴充套件API和證書透明系統有影響)。
  • 在TLS 1.3連線中不再允許使用DSA證書。

注意,在這一階段,只支援TLS 1.3。因DTLS 1.3版本的規範剛剛開始制定,目前並不支援OpenSSL。

TLS 1.3 標準目前的狀態

到我寫這篇文章時,TLS 1.3仍是一個草案。TLS工作團隊定期會發布該標準的新版草案。實際中,需要對草案進行部署來識別他們使用的具體版本,基於不同草案版本的實現之間無法互動。

OpenSSL 1.1.1至少不會在TLS 1.3釋出之前完成。同時,OpenSSL的git主分支包含了我們的TLS 1.3開發程式碼,可以用於測試(即不用於生產)。你可以在任意OpenSSL版本中透過標頭檔案tls1.h中的宏TLS1_3_VERSION_DRAFT_TXT的值來檢視部署的TLS 1.3草案的版本。在該標準的最終版釋出後,這個宏會被刪除。

你必須使用“enable-tls1_3”選項來“配置”(config或Configure),以編譯OpenSSL,使其支援TLS 1.3。

目前,OpenSSL已執行了TLS 1.3的“20版草案”。而很多其他庫仍在使用舊版草案。相當多的主流瀏覽器在使用“18版草案”。這是互動性問題產生的共同來源。18版草案的互動性已被BoringSSL、NSS和picotls測試過。

在OpenSSL的hit原始碼庫中有兩個分支:“tls1.3-draft-18”和“tls1.3-draft-19”,都執行舊的TLS 1.3草案版本。為測試其它TLS 1.3版本環境下的互動性,你可能需要使用其中一個分支。注意那些分支被認為是臨時的,而且當將來不再需要它們時,可能會被刪除。

密碼套件

OpenSSL已支援以下5種TLS 1.3的密碼套件:

  • TLS13-AES-256-GCM-SHA384
  • TLS13-CHACHA20-POLY1305-SHA256
  • TLS13-AES-128-GCM-SHA256
  • TLS13-AES-128-CCM-8-SHA256
  • TLS13-AES-128-CCM-SHA256

其中,前三個是在預設密碼套件組中。這意味著如果你沒有主動對密碼套件進行配置,那麼你會自動使用這三個密碼套件,並可以進行TLS 1.3磋商。

所有TLS 1.3密碼套件也都出現在別名HIGH中。正如你預計的那樣,CHACHA20、AES、AES128、AES256、AESGCM、AESCCM和AESCCM8這些密碼套件別名都像它們的名稱一樣,且包含這些密碼套件的一個子集。金鑰交換和認證屬性是TLS 1.2及以前版本中密碼套件定義的一部分。在TLS 1.3中不再如此,所以密碼套件別名(如ECHHE、ECDSA、RSA及其它相似別名)都不包含任何TLS 1.3密碼套件。

如果你主動配置了你的密碼套件,那麼應該注意確保你沒有不小心排除掉所有相容TLS 1.3的密碼套件。如果一個客戶端啟用了TLS 1.3而未配置TLS 1.3密碼套件,那麼會立即報錯(即使伺服器不支援TLS 1.3),出現以下提示:

1

 

140460646909376:error:141A90B5:SSL routines:ssl_cipher_list_to_bytes:no ciphers available:ssl/statem/statem_clnt.c:3562:No ciphers enabled for max supported SSL/TLS version

類似地,如果一個伺服器啟用了TLS 1.3而未配置TLS 1.3密碼套件,那麼也會立即報錯,即使客戶端不支援TLS 1.3,提示如下:

1

 

140547390854592:error:141FC0B5:SSL routines:tls_setup_handshake:no ciphers available:ssl/statem/statem_lib.c:108:No ciphers enabled for max supported SSL/TLS version

例如,預設設定一個密碼套件選擇字串ECDHE:!COMPLEMENTOFDEFAULT,還使用ECDHE進行金鑰交換。但是,ECDHE組中沒有TLS 1.3密碼套件,所以如果啟用了TLS 1.3,那麼這種密碼套件配置在OpenSSL 1.1.1中將會出錯。你可能要指定你想使用的TLS 1.3密碼套件來避免出現問題。例如:

1

 

“TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-256-GCM-SHA384:ECDHE:!COMPLEMENTOFDEFAULT”

你可以使用openssl ciphers -s -v命令來測試,在給定的密碼套件選擇字串中包含那個密碼套件:

1

 

$ openssl ciphers -s -v “ECDHE:!COMPLEMENTOFDEFAULT”

確保至少有一個密碼套件支援TLS 1.3

在TLS 1.3中,客戶端選擇一個“組”用來進行金鑰交換。在我撰文時,OpenSSL僅支援ECDHE組(當OpenSSL 1.1.1自動釋出時,可能就會支援DHE組了)。客戶端會在客戶端問候訊息中為其所選的組傳送“key_share”資訊到伺服器。

支援的組的名單是可配置的。一個客戶端可能會選擇一個伺服器不支援的組。在這種情況下,伺服器請求客戶端傳送一個其新支援的key_share。這意味著仍會建立連線(假設存在一個互相支援的組),會引入一個額外的伺服器雙向連線——所以會對效能產生影響。在理想情況下,客戶端將在第一個例項中選擇一個伺服器支援的組。

實際上,多數客戶端都會為它們的首個key_share使用 X25519或P-256。為實現效能最大化,建議對伺服器進行配置,使其至少支援這兩個組,客戶端為其首個key_share使用其中一個組。這是預設的情況(OpenSSL客戶端將使用X25519)。

組配置還控制著TLS 1.2及以前版本中允許的組。如果應用程式在OpenSSL 1.1.0中曾配置過它們的組,那麼你應該重新檢查配置,以確保其對TLS 1.3仍然有效。第一個被指定的組(即最偏好的組)將會被一個OpenSSL客戶端在其首次key_share中使用。

應用程式可以使用SSL_CTX_set1_groups()或一個相似的函式(看這裡)配置組列表。如果應用程式使用SSL_CONF風格配置檔案,則可以使用Groups或Curves命令(看這裡)來進行配置。

會話

在TLS 1.2及以前版本中,一個會話的建立是握手的一部分。這個會話就可以在後續連線中被使用,以實現一個簡單握手。一般,在握手完成後,應用程式可能透過使用SSL_get1_session()函式(或類似函式)從會話上得到一個控制程式碼。更多細節請看這裡。

在TLS 1.3中,直到主握手完成後,會話才會建立。伺服器傳送一個獨立的握手後訊息(包含會話細節)到客戶端。通常,這會發生在握手結束後不久,也可能會稍晚一些(甚至根本不發生)。

按照規範,建議應用程式每次只使用一個會話(即使不是強制性的)。由於這個原因,一些伺服器會向一個客戶端傳送多個會話訊息。為執行“每次使用一個”的建議,應用程式可以使用SSL_CTX_remove_session()把一個使用過的會話標記為不可恢復(從快取中將其刪除)。舊的SSL_get1_session()和相似API可能像TLS 1.2及以前版本中一樣執行。具體來說,如果一個客戶端應用程式在收到包含會話細節的伺服器訊息之前就呼叫SSL_get1_session(),那麼仍將返回一個SSL_SESSION物件,任何試圖恢復的企圖都不會成功,而是會產生一個完整的握手。在伺服器傳送多個會話的情況下,只有最後一個會話被SSL_get1_session()返回。

客戶端應用程式開發者應該考慮使用SSL_CTX_sess_set_new_cb() API(看這裡)。這提供一個回撥機制,每次新的會話建立時該機制都會被呼叫。如果伺服器傳送多個會話訊息,就可以為一個連線呼叫多次。

注意,SSL_CTX_sess_set_new_cb()在OpenSSL 1.1.0中仍然可用。已使用的那個API應用程式仍可以工作,但它們可能會發現,回撥機制被呼叫的時機變了,變成了在握手之後發生。

在主握手完成後,一個OpenSSL伺服器將立即嘗試發生會話細節到客戶端。對伺服器應用程式來說,這一握手後的階段看起來像是主握手的一部分,所以對SSL_get1_session()的呼叫應該像以前一樣繼續工作。

定製擴充套件和證書透明系統

在TLS 1.2及以前版本中,首次客戶端問候資訊和伺服器問候資訊可以包括“擴充套件”。這允許基礎規定可以被新增很多額外特性,這些特性可能無法在所有情況下使用,或者在制定基礎規定時無法預見。OpenSSL支援大量“內建”擴充套件。

此外,定製擴充套件API還為應用程式開發人員提供一些基本功能,以支援沒有內建在OpenSSL中的新擴充套件。

建立在定製擴充套件API頂層的是“伺服器資訊”API。這提供了一個更加基礎性的介面,可以在執行時進行配置。例如證書透明系統。OpenSSL為證書透明系統的客戶端提供內建支援,但沒有內建伺服器端支援。但是,用“伺服器資訊”檔案就很容易實現。一個包含證書透明系統資訊的伺服器資訊檔案可以在OpenSSL中配置,再被正確地發回客戶端。

在TLS 1.3中,擴充套件的使用顯著增加,有很多訊息包含擴充套件。此外,一些支援TLS 1.2及以前版本的擴充套件在TLS 1.3中不再被支援,一些擴充套件從伺服器問候訊息轉移到了加密擴充套件訊息中。舊的定製擴充套件API沒有能力指定擴充套件應該關聯的訊息。

由於這個原因,需要有一個新的定製擴充套件API。

舊API仍在工作,但定製擴充套件將只在TLS 1.2及以前版本環境下被新增。想要為所有TLS版本新增定製擴充套件,應用程式開發人員就需要把他們的應用程式更新到新的API(更多詳情看這裡)。

“伺服器資訊”資料格式也已被更新,以包含額外的關於擴充套件所關聯的訊息的資訊。使用“伺服器資訊”檔案的應用程式可能需要更新到“版本2”的檔案格式,才能在TLS 1.3中執行(更多細節看這裡和這裡)。

重新磋商

TLS 1.3沒有重新磋商機制,所以在TLS 1.3環境下,對SSL_renegotiate()和SSL_renegotiate_abbreviated()的呼叫會立即失敗。

重新磋商最常見的例子是更新連線金鑰。再TLS 1.3中,函式SSL_key_update()可以用於的這個目的(看這裡)。

DSA 證書

TLS 1.3中不再允許DSA證書。如果你的伺服器應用程式正在使用DSA證書,那麼TLS 1.3連線將會失敗,提示如下:

1

 

140348850206144:error:14201076:SSL routines:tls_choose_sigalg:no suitable signature algorithm:ssl/t1_lib.c:2308:

請使用ECDSA或RSA證書。

結論

TLS 1.3代表著一次重大進步,它有一些激動人心的特性,但對粗心的人來說,在更新時可能會有一些風險。大部分時候,這些問題都會有直接的解決辦法。應用程式開發人員應該重新檢查他們的程式碼,並考慮為更高效地使用TLS 1.3,是否應該安裝所有更新。類似地,部署人員也應該重新檢查他們的配置。

全球可信CA機構

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31483669/viewspace-2678195/,如需轉載,請註明出處,否則將追究法律責任。

相關文章