日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

OpenSSL状态机中可选消息的处理

發(fā)布時(shí)間:2025/3/20 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenSSL状态机中可选消息的处理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

openssl在實(shí)現(xiàn)ssl握手的時(shí)候是用狀態(tài)機(jī)實(shí)現(xiàn)的,實(shí)際上linux內(nèi)核的tcp協(xié)議也是狀態(tài)機(jī)實(shí)現(xiàn)的,原因就在于這些協(xié)議本身的握手規(guī)則就是狀態(tài)機(jī)(簡(jiǎn)直是廢話)。SSLv3握手規(guī)則要比tcp復(fù)雜的多,因此它的實(shí)現(xiàn)如果要既美觀又高效的話就一定需要很多技巧,造成這種結(jié)果的原因就在于ssl握手過程中存在很多的可選消息,而這些可選消息是否存在并不簡(jiǎn)單依賴與前一個(gè)或者前若干個(gè)消息的消息頭,而只有解析了前面的消息體內(nèi)容之后才能知道是否存在可選消息,在這個(gè)意義上可以說客戶端的握手狀態(tài)機(jī)實(shí)現(xiàn)要么保存曾經(jīng)的消息遺留的狀態(tài),要么不保留狀態(tài),默認(rèn)按狀態(tài)機(jī)轉(zhuǎn)化順序處理任何消息(還好,狀態(tài)機(jī)有且只有一種順序),如果采用前一個(gè)方案的話,那么勢(shì)必要在握手規(guī)則和消息處理handler之間進(jìn)行耦合,如果那一天改變了一方的框架,就會(huì)導(dǎo)致另一方的改變,openssl的實(shí)現(xiàn)采用了后一種解決方案巧妙的解決了這個(gè)問題,不管怎樣狀態(tài)機(jī)順序地在所有可能的狀態(tài)中轉(zhuǎn)變,每一個(gè)狀態(tài)中調(diào)用固定的處理函數(shù),然后在處理函數(shù)中采用了一個(gè)技巧:處理函數(shù)首先不去下面的BIO(一般是tcp套接字)中讀消息,而是先檢查一個(gè)標(biāo)志reuse,如果這個(gè)標(biāo)志置位了,那么就清除這個(gè)標(biāo)志,取上次讀到的消息后返回,在返回狀態(tài)機(jī)處理handler之后,首先根據(jù)得到消息的頭判斷其類型是否是狀態(tài)機(jī)處于該狀態(tài)所處理消息的對(duì)應(yīng)類型,如果不是,上述的reuse標(biāo)志重新置位,handler返回,狀態(tài)機(jī)推進(jìn)到下一個(gè)狀態(tài),從而在接下來的狀態(tài)處理當(dāng)中不再?gòu)奶捉幼肿x取消息。大致框架就是:
state_machine()
{
??? while (true) {
??? ??? switch (state)
??? ??? ??? case s1:
??? ??? ??? ??? handler1(param);
??? ??? ??? ??? state = s2;
??? ??? ??? ??? break;
??? ??? ??? case s2:
??? ??? ??? ??? handler2(param);
??? ??? ??? ??? state = s3;
??? ??? ??? ??? break;
??? ??? ??? case s3:
??? ??? ??? ??? handler3(param);
??? ??? ??? ??? state = s4;
??? ??? ??? ??? break;
??? ??? ??? ...
??? }
}
如果s2狀態(tài)所對(duì)應(yīng)的消息是可選的,但是s3是必須的狀態(tài),并且此次此時(shí)并不需要處理s2這個(gè)狀態(tài),但是handler2中確實(shí)要讀取消息,怎么辦呢?如果真的從套接字讀取消息的話,那么處理就會(huì)亂掉,handler2中讀取的是s3狀態(tài)所對(duì)應(yīng)的消息,那么怎么處理呢?openssl的方式是在case s2中調(diào)用handler2之中判斷一下當(dāng)前讀到消息的類型,如果不是對(duì)應(yīng)于s2的消息,那就說明s2狀態(tài)所對(duì)應(yīng)的消息不存在,于是在case s2的handler中進(jìn)行完判斷之后,將一個(gè)reuse標(biāo)志設(shè)置上,于是在s3狀態(tài)中的s3處理中首先判斷是否有reuse標(biāo)志,如果有的話,那么就不再?gòu)奶捉幼肿x取消息,而是將在handler2中讀取的消息返回,并且清除reuse標(biāo)志,之后以此類推。總結(jié)一下就是只要在可選消息的handler處理之后,都要進(jìn)行類似s2處理的判斷,如果失敗就將reuse設(shè)置。
???? 但是這又引出了另外一個(gè)問題,那就是在每個(gè)handler中都要判斷reuse標(biāo)志,這個(gè)工作實(shí)在繁重,狀態(tài)機(jī)處理是解放了,每個(gè)狀態(tài)的handler的任務(wù)卻更加繁重了,任何好的設(shè)計(jì)需要做到的就是盡量將繁雜的判斷放到穩(wěn)定的邏輯當(dāng)中,狀態(tài)機(jī)是不穩(wěn)定的,因?yàn)橛泻芏嗫蛇x狀態(tài),每個(gè)狀態(tài)的handler也不是穩(wěn)定的,因?yàn)槊總€(gè)狀態(tài)的處理太復(fù)雜了,隨著版本的更新,任何細(xì)節(jié)的改變都會(huì)導(dǎo)致大量的更改,于是openssl就把這個(gè)邏輯抽取出來,專門放到SSL_METHOD的一個(gè)回調(diào)函數(shù)ssl3_get_message中,在調(diào)用完這個(gè)回調(diào)函數(shù)之后馬上檢查讀到的消息類型是否是我們本狀態(tài)要處理的類型,如果不是,那么馬上將reuse設(shè)置為1,我們看一下ssl_get_message中在真正在套接字上讀取消息之前的一個(gè)處理:
if (s->s3->tmp.reuse_message)
{
??? s->s3->tmp.reuse_message=0;
??? if ((mt >= 0) && (s->s3->tmp.message_type != mt)) {
??? ??? ...
??? }
??? *ok=1;
??? s->init_msg = s->init_buf->data + 4;
??? s->init_num = (int)s->s3->tmp.message_size;
??? return s->init_num;
}
以上代碼是s->method->ssl_get_message中首先要調(diào)用的,對(duì)應(yīng)上面代碼的另一部分在ssl3_connect中可選消息handler的調(diào)用之后,以ssl3_get_key_exchange為例:
int ssl3_get_key_exchange(SSL *s)
{
...
??? n=s->method->ssl_get_message(s,
??? ??? SSL3_ST_CR_KEY_EXCH_A,
??? ??? SSL3_ST_CR_KEY_EXCH_B,
??? ??? -1,
??? ??? s->max_cert_list,
??? ??? &ok);
...
??? if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) {
??? ??? s->s3->tmp.reuse_message=1;
??? ??? return(1);
??? }
...
}
openssl的這種實(shí)現(xiàn)使得握手狀態(tài)機(jī)處理看起來十分清晰,所有的處理消息是否可選的邏輯都隱藏到了邏輯比較單一的回調(diào)函數(shù)中,然后在邏輯復(fù)雜的處理函數(shù)中簡(jiǎn)單判斷即可,這種分離比SSLv2的設(shè)計(jì)要更好,在SSLv2的狀態(tài)機(jī)實(shí)現(xiàn)中,每一個(gè)狀態(tài)處理完了之后就會(huì)判斷結(jié)果,然后根據(jù)結(jié)果去設(shè)置下一個(gè)狀態(tài),其實(shí)這種方式更像是一個(gè)狀態(tài)機(jī),SSLv3的實(shí)現(xiàn)反而不像狀態(tài)機(jī)了,一個(gè)一個(gè)順序的處理,沒有變數(shù),這種情況其實(shí)完全不用狀態(tài)機(jī)實(shí)現(xiàn),一個(gè)順序執(zhí)行的函數(shù)就可以了,連循環(huán)都不用,誰知道以后的版本會(huì)怎樣呢。

轉(zhuǎn)載于:https://blog.51cto.com/dog250/1271994

總結(jié)

以上是生活随笔為你收集整理的OpenSSL状态机中可选消息的处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。