mozilla的安全架構
mozilla在安全方面主要分為三大塊:1.SSL協議的實現;2.Crypto庫的實現;3.PKCS#11的實現最頂層是ssl的實現,和openssl不同,mozilla是自上而下設計的,因此mozilla並沒有抽象出諸如BIO或者EVP之類的通用機制,可以它實現了一個PRFileDesc結構體,和BIO是很類似的;涉及到安全的實現就是2和3了,其中3定義了介面,2給與了軟實現,當然你可以載入plugin使用硬體實現。三者合一形成了mozilla的安全架構。
有幾個重要的結構體先了解一下:sslSocketStr結構和openssl中的ssl_st結構體非常類似:
struct sslSocketStr {
PRFileDesc * fd; //一個檔案IO分發表,類似linux核心的file_operations,僅僅作為介面定義。
const sslSocketOps * ops //實現PRFileDesc的介面定義;
…
sslSecurityInfo sec; //操作ssl通道的方式,比如加密,解密之類
…
const char *url; //目的地址,瀏覽器接受的url
…
sslHandshakeFunc handshake; //函式可以作為鎖來使用
sslHandshakeFunc nextHandshake;
sslHandshakeFunc securityHandshake;
//回撥函式,timeout,lock,暫存緩衝,執行緒,ssl握手方法,狀態
};
上面的一個sslSocketStr代表了一個連線,並且描述了表示層即ssl協議,和openssl類似,mozilla也永術語“PUSH”來將一個安全描述符壓入一個普通的傳輸層套接字(類似OpenSSL的BIO機制,後面會說),比如你訪問http://www.google.com.hk,那麼敲下回車的時候就會建立一個sslSocketStr,其中url就是你要訪問的google的網址,某些網站需要安全連線,如果需要安全的話隨之就會初始化sslSocketStr中的fd中的PRIOMethods為ssl_methods,它完成了套接字IO的幾乎所有的語義,在openssl中,該結構體由SSL_METHOD實現,原理和此處的mozilla幾乎一致:
static const PRIOMethods ssl_methods = {
PR_DESC_LAYERED,
…
ssl_Read, //read
ssl_Write, //write
ssl_Recv, //recv
ssl_Send, //send
…
};
static const sslSocketOps ssl_secure_ops = {
…
ssl_SecureRecv,
ssl_SecureSend,
…
};
為何要有PRIOMethods和sslSocketOps兩個結構體呢?看起來一個就夠了,答案是為了實現分層模型,PRIOMethods並沒有具體的實現策略,只是表示一個“協議層”的語義,對於ssl的具體實現當然沒有必要在ssl層就全做掉,因為即使選擇ssl也可以有不同的策略,也就需要再來一個結構體了,特別是,這樣可以不加區分地統一使用一致的SSL介面,在不實現ssl的情況下,可以再實現一個ssl_default_ops(security/nss/lib/ssl/sslsock.c)。
ssl_Do1stHandshake完成了ssl握手時的狀態機轉換,mozilla並不區分client方法和server方法,而是完全按照RFC2246的規定來實現ssl,對於client端,在ssl_SecureConnect中會發起對server的連線,也就是傳送一個ClientHello訊息,此時會將sslSocketStr的securityHandshake設定為ssl2_BeginClientHandshake(僅對ssl2來說),接下來任何的讀寫ssl,都會呼叫PRIOMethods中的recv/send函式,然後就回進入到ssl_Do1stHandshake狀態機,在其中client會呼叫到這個剛剛設定的ssl2_BeginClientHandshake函式,在該函式最後,按照RFC2246的規定,會進行如下設定:
ss->handshake = ssl_GatherRecord1stHandshake;
ss->nextHandshake = ssl2_HandleServerHelloMessage;
握手回撥函式handshake自己維護狀態機,這一點和openssl不同,在handshake的呼叫最後,函式根據呼叫結果和當前狀態將nexthandshake按照RFC2246設定成下一個狀態,然後在ssl_Do1stHandshake將狀態機向前推進:
int ssl_Do1stHandshake(sslSocket *ss)
{
do {
if (ss->handshake == 0) {
ss->handshake = ss->nextHandshake;
ss->nextHandshake = 0;
}
if (ss->handshake == 0) {
ss->handshake = ss->securityHandshake;
ss->securityHandshake = 0;
}
…
//握手完畢時要退出迴圈
rv = (*ss->handshake)(ss);
++loopCount;
} while (rv != SECFailure);
…
}
ssl握手的後半部分會根據協商內容設定cipher,設定cipher也就部分初始化了sslSocketStr的sec欄位,在ssl2_CreateSessionCypher(由狀態處理函式ssl2_XYZSetupSessionCypher呼叫)確定ss->sec.enc函式指標PK11_CipherOp,從此,所有的資料傳輸都要經過加密,加密的方法就是PK11_CipherOp,mozilla通過封裝p11介面來統一處理安全通道的配置以及使用過程。
PRFileDesc作為一個解耦層(很重要,不僅僅解除了各個模組耦合,而且還實現了一個分層的模型),將操作路由到sslSocketOps,而sslSocketOps中同樣可以根據ssl的不同狀態或者不同配置將操作繼續路由,比如在ssl_SecureSend中會呼叫:
rv = (*ss->sec.send)(ss, buf, len, flags);
可見sec欄位的send也是一個可變更的回撥函式,總體的過程就是:
首先ss->fd->methods->send[ssl_Send]:
rv = (*ss->ops->send)(ss, (const unsigned char*)buf, len, flags);[ssl_SecureSend]:
rv = (*ss->sec.send)(ss, buf, len, flags);[ssl2_SendBlock]:
ssl_DefSend.
最終ssl_DefSend將資料傳送了出去,通過socket將資料傳送了出去。
有幾個重要的結構體先了解一下:sslSocketStr結構和openssl中的ssl_st結構體非常類似:
struct sslSocketStr {
PRFileDesc * fd; //一個檔案IO分發表,類似linux核心的file_operations,僅僅作為介面定義。
const sslSocketOps * ops //實現PRFileDesc的介面定義;
…
sslSecurityInfo sec; //操作ssl通道的方式,比如加密,解密之類
…
const char *url; //目的地址,瀏覽器接受的url
…
sslHandshakeFunc handshake; //函式可以作為鎖來使用
sslHandshakeFunc nextHandshake;
sslHandshakeFunc securityHandshake;
//回撥函式,timeout,lock,暫存緩衝,執行緒,ssl握手方法,狀態
};
上面的一個sslSocketStr代表了一個連線,並且描述了表示層即ssl協議,和openssl類似,mozilla也永術語“PUSH”來將一個安全描述符壓入一個普通的傳輸層套接字(類似OpenSSL的BIO機制,後面會說),比如你訪問http://www.google.com.hk,那麼敲下回車的時候就會建立一個sslSocketStr,其中url就是你要訪問的google的網址,某些網站需要安全連線,如果需要安全的話隨之就會初始化sslSocketStr中的fd中的PRIOMethods為ssl_methods,它完成了套接字IO的幾乎所有的語義,在openssl中,該結構體由SSL_METHOD實現,原理和此處的mozilla幾乎一致:
static const PRIOMethods ssl_methods = {
PR_DESC_LAYERED,
…
ssl_Read, //read
ssl_Write, //write
ssl_Recv, //recv
ssl_Send, //send
…
};
static const sslSocketOps ssl_secure_ops = {
…
ssl_SecureRecv,
ssl_SecureSend,
…
};
為何要有PRIOMethods和sslSocketOps兩個結構體呢?看起來一個就夠了,答案是為了實現分層模型,PRIOMethods並沒有具體的實現策略,只是表示一個“協議層”的語義,對於ssl的具體實現當然沒有必要在ssl層就全做掉,因為即使選擇ssl也可以有不同的策略,也就需要再來一個結構體了,特別是,這樣可以不加區分地統一使用一致的SSL介面,在不實現ssl的情況下,可以再實現一個ssl_default_ops(security/nss/lib/ssl/sslsock.c)。
ssl_Do1stHandshake完成了ssl握手時的狀態機轉換,mozilla並不區分client方法和server方法,而是完全按照RFC2246的規定來實現ssl,對於client端,在ssl_SecureConnect中會發起對server的連線,也就是傳送一個ClientHello訊息,此時會將sslSocketStr的securityHandshake設定為ssl2_BeginClientHandshake(僅對ssl2來說),接下來任何的讀寫ssl,都會呼叫PRIOMethods中的recv/send函式,然後就回進入到ssl_Do1stHandshake狀態機,在其中client會呼叫到這個剛剛設定的ssl2_BeginClientHandshake函式,在該函式最後,按照RFC2246的規定,會進行如下設定:
ss->handshake = ssl_GatherRecord1stHandshake;
ss->nextHandshake = ssl2_HandleServerHelloMessage;
握手回撥函式handshake自己維護狀態機,這一點和openssl不同,在handshake的呼叫最後,函式根據呼叫結果和當前狀態將nexthandshake按照RFC2246設定成下一個狀態,然後在ssl_Do1stHandshake將狀態機向前推進:
int ssl_Do1stHandshake(sslSocket *ss)
{
do {
if (ss->handshake == 0) {
ss->handshake = ss->nextHandshake;
ss->nextHandshake = 0;
}
if (ss->handshake == 0) {
ss->handshake = ss->securityHandshake;
ss->securityHandshake = 0;
}
…
//握手完畢時要退出迴圈
rv = (*ss->handshake)(ss);
++loopCount;
} while (rv != SECFailure);
…
}
ssl握手的後半部分會根據協商內容設定cipher,設定cipher也就部分初始化了sslSocketStr的sec欄位,在ssl2_CreateSessionCypher(由狀態處理函式ssl2_XYZSetupSessionCypher呼叫)確定ss->sec.enc函式指標PK11_CipherOp,從此,所有的資料傳輸都要經過加密,加密的方法就是PK11_CipherOp,mozilla通過封裝p11介面來統一處理安全通道的配置以及使用過程。
PRFileDesc作為一個解耦層(很重要,不僅僅解除了各個模組耦合,而且還實現了一個分層的模型),將操作路由到sslSocketOps,而sslSocketOps中同樣可以根據ssl的不同狀態或者不同配置將操作繼續路由,比如在ssl_SecureSend中會呼叫:
rv = (*ss->sec.send)(ss, buf, len, flags);
可見sec欄位的send也是一個可變更的回撥函式,總體的過程就是:
首先ss->fd->methods->send[ssl_Send]:
rv = (*ss->ops->send)(ss, (const unsigned char*)buf, len, flags);[ssl_SecureSend]:
rv = (*ss->sec.send)(ss, buf, len, flags);[ssl2_SendBlock]:
ssl_DefSend.
最終ssl_DefSend將資料傳送了出去,通過socket將資料傳送了出去。
上述的過程不是很難理解,而且實現的很合理,mozilla更合理的一個地方就是通過PKCS#11介面來統一封裝所有的安全操作,為何通過p11封裝呢?我覺得p11主要用於客戶端,解決了客戶端安全加密的一系列問題,而瀏覽器也在客戶端,因此使用p11會十分方便,雖然可能機器上沒有usbkey,但是軟實現的P11一樣好用,畢竟p11只是一個規範,p11的軟實現會呼叫mozilla安全框架的另一部分,那就是crypto介面(類似openssl的EVP)。
本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1271800
相關文章
- 專案-安全架構架構
- 企業安全架構架構
- 建立雲安全架構的5個技巧架構
- 安全架構中的前端安全防護架構前端
- 安全架構評審實戰架構
- 零信任安全架構應如何落地?架構
- 網路安全架構規劃策略架構
- 大型網站技術架構(八)--網站的安全架構網站架構
- NB-IOT物聯網系統的安全架構架構
- Kubernetes 下零信任安全架構分析架構
- BeyondCorp 打造得物零信任安全架構架構
- ASP.NET安全架構--如何實現.NET安全ASP.NET架構
- 如何保證網站的安全架構,不被黑客攻擊網站架構黑客
- 如何建設網路安全架構及防禦措施?架構
- Spring認證-Spring 安全架構專題教程Spring架構
- EasyMR 安全架構揭秘:如何管理 Hadoop 資料安全架構Hadoop
- 田汽車張靈通:整體網路安全架構架構
- 跟著大公司學安全之BeyondCorp安全架構架構
- Android 安全架構及許可權控制機制剖析Android架構
- 《大型網際網路企業安全架構》讀書筆記架構筆記
- 關於Mozilla崩潰的研究
- mozilla css developer centerCSSDeveloper
- Mozilla UserAgent 總結
- Mozilla瀏覽器瀏覽器
- 當金融科技遇上雲原生,螞蟻金服是怎麼做安全架構的?架構
- 全新架構 全速發展 美創科技新一代資料安全架構正式釋出架構
- WebAssembly Studio:Mozilla提供的WASM工具WebASM
- 網易易盾首席安全架構師沈明星分享DDoS防護如何建設架構
- linux下Acrobat和mozilla的整合(轉)LinuxBAT
- 乾貨:以資料為中心的多層防禦,集中管控式大資料安全架構大資料架構
- 阿里雲安全肖力:雲原生安全定義下一代安全架構阿里架構
- TogetherJS:Mozilla推出的實時協作工具JS
- 通往 Rust 1.0 之路,Mozilla 新的程式語言Rust
- Linux下使用mozilla的幾個問題Linux
- 讓你的Mozilla支援XML資料島 (轉)XML
- Mozilla 瀏覽器四歲了!瀏覽器
- 阿里巴巴釋出新一代安全架構:讓數字基建的每塊磚安全可溯源阿里架構
- 打造全場景、可信任、實戰化的安全架構,智慧安全3.0為智慧城市保駕護航架構