1、概述
DTLS即Datagram Transport Layer Security (RFC4347),AP加入AC前,先進行DTLS驗證,當AP與AC之間的DTLS握手成功后,AP發出Join請求開始請求加入。這個過程里面的所有報文均為加密報文。以下為報文格式(摘自RFC5418):
在我們的代碼中是在CWWTPEnterJoin()函數中來實現的。
2、代碼分析
主要的函數以下幾個過程:
CWStateTransition CWWTPEnterJoin() {
//初始化socket gWTPSocket
/* Init DTLS session */
if(!CWErr(CWNetworkInitSocketClient(&gWTPSocket,
&(gACInfoPtr->preferredAddress))) ) {
timer_rem(waitJoinTimer, NULL);
return CW_ENTER_DISCOVERY;
}
#ifndef CW_NO_DTLS
if(gACInfoPtr->security == CW_X509_CERTIFICATE) {//需要授權書
if(!CWErr(CWSecurityInitContext(&gWTPSecurityContext,//初始化wtp本地加密策略
"root.pem",
"client.pem",
"prova",
CW_TRUE,
NULL)))
}
#endif
CWThread thread_receiveFrame;
if(!CWErr(CWCreateThread(&thread_receiveFrame, //開啟接受dtls數據的線程
CWWTPReceiveDtlsPacket,
(void*)gWTPSocket)))
#ifndef CW_NO_DTLS
if(!CWErr(CWSecurityInitSessionClient(gWTPSocket,//初始化DTSL會話
&(gACInfoPtr->preferredAddress),
gPacketReceiveList,
gWTPSecurityContext,
&gWTPSession,
&gWTPPathMTU)))
if(!CWErr(CWWTPSendAcknowledgedPacket(seqNum, //發起Join 會話請求。
NULL,
CWAssembleJoinRequest,
(void*)CWParseJoinResponseMessage,
(void*)CWSaveJoinResponseMessage,
&values)))
CWLog("Join Completed");
return CW_ENTER_CONFIGURE;
}
DTSL會話初始化主要在CWSecurityInitSessionClient中完成。
3、DTLS 握手
根據協議介紹,DTLS 握手包含如下幾個步驟:
- WTP首先發送一個ClientHello消息來發起握手,說明它支持的密碼算法列表、壓縮方法及最高協議版本和其他一些需要的消息。
- AC回復一個HelloVerifyReuqest 消息,client必須重傳添加了cookie的ClientHello。server然后驗證cookie,如果有效的話才開始進行握手。
- AC回應一個ServerHello消息,包含服務器選擇的連接參數,源自客戶端初期所提供的ClientHello,確定了這次通信所需要的算法,然后發過去自己的證書(里面包含了身份和自己的公鑰)。
- Client在收到這個消息后會生成一個秘密消息,用SSL服務器的公鑰加密后傳過去,SSL服務器端用自己的私鑰解密后,會話密鑰協商成功,雙方可以用同一份會話密鑰來通信了。
而在我們的代碼中,
CWDebugLog("Before HS");
CWSecurityManageSSLError(SSL_do_handshake(*sessionPtr),
*sessionPtr,
SSL_free(*sessionPtr););
CWDebugLog("After HS");
if (SSL_get_verify_result(*sessionPtr) == X509_V_OK) {
CWDebugLog("Certificate Verified");
} else {
CWDebugLog("Certificate Error (%d)",
SSL_get_verify_result(*sessionPtr));
}
總結:
DTLS 握手是通過SSL_do_handshake這個函數來實現的,而在我們上次的調試過程中發現也是這個地方出錯。但是這個函數是openSSL加密庫的函數,在openCawwap中沒有實現。