這幾天終於搞定了AES硬件加密工具的使用,幾種簡單的加密模式也都實驗通過了,比較麻煩的一種是CCM模式的加密,它是CTR加密模式和CMAC認證算法的混合使用。本文先介紹CCM模式的原理與基本實現,然后結合OpenSSL的加密庫,了解一下具體過程,最后,在AES硬件加密引擎上實現。
CCM介紹
CCM是CTR加密模式和CMAC認證算法的混合使用,常用在需要同時加密和認證的領域,比如WiFi安全中的WPE協議,它就使用了AES-CCM模式。
CCM首先使用CBC-MAC模式來認證傳輸幀,然后使用CTR模式來加密幀。在這里,用於加密的初始化向量IV構成結構如下:
sequence counter表示在一個幀中16個字節塊的數目. Flags域結構如下:
Bit7設置為0,Adata為1的話,表示此幀有額外的認證數據,為0則表示沒有額外的認證數據。M為認證域長度經過轉換后的結果.L固定為1. 在不同的安全模式下,初始化向量中的Flags值不同。從上表可以看出,只要有MIC的存在,那么Adata就必須為1.
首先引入兩個CCM模式下的兩個參數:
L : 長度域,取值為2~8, OpenSSL中缺省為8
M : tag的長度,可選范圍為4,6,8,10,12,14,16.OpenSSL中缺省為12
接下來,將詳細描述如何在硬件加密模塊上實現CCM模式的認證和加密。
在硬件AES加密引擎上面,沒有完整的實現CCM模式的加密,需要軟硬件一起配合,才能實現CCM模式。
在CCM模式下CBC-MAC
對於待加密數據中的前數據塊,采用CBC-MAC模式加密生成認證域,對於最后一個數據塊,需要改為使用CBC模式加密。當最后一個數據塊載入AES硬件加密引擎后,從AES讀出的就是消息的MAC校驗碼。
在CCM模式下CTR
以下是認證執行的步驟。
1. 載入加密密鑰
2. 載入全0的初始化向量
3. 構建一個16個字節的數組B,其第一個元素B[0]需要有如下的構造。
其中,Flag的值和安全級別有關系,具體關系間下表。
其他內容元素按規則來填充。
4. 按照16字節加密塊來划分,第一個塊填充初始化向量,第二個塊填充Adata相關內容,第三個塊(或者更多塊)填充明文內容
5. 先按照CBC_MAC模式加密前N-1個塊,最后一個數據塊使用CBC模式來加密.當認證域長度為16時,CBC_MAC加密后的內容是不變的,如果不為16,則高M字節內容保持不變,其余字節變為0.
6. 等待加密完成后,從結果中,讀出Mval個字節到Cstate就可以了。
函數頭說明:
void Test_SSP_CCM_Auth (uint8 Mval, // 認證域字節長度 [0,4,8,16]
uint8 *N, // N 指向13字節的隨機數
uint8 *M, // M 指向明文的指針
uint16 len_m, // len_m 明文長度
uint8 *A, // A 指向Adata的指針
uint16 len_a, // len_a 數據長度
uint8 *AesKey, //AesKey 指向密鑰的指針
uint8 *Cstate) //輸出Cstate 緩存
加密步驟:
CCM模式下的加密,需要使用前面生產的Cstate值,具體使用步驟如下:
加密也需要初始化向量,其構成如下:
當在OFB模式,將認證域加密生產U時,CTR的值必須為0,當在CTR模式,CTR的值必須不為0
1. 創建A塊,並按照規則來填充A[0],當做后的IV
2. 創建T塊,將Cstate的前Mval填充到T中。
3.分配緩存,用於填充輸入明文,不足16字節的補0.
4. 以OFB模式,將明文T加密輸出到Cstate[也叫做U]。當認證域長度為16時,上傳緩存內容保持不變,如果不為16,則上傳內容的高M位保持不變,其余字節變為0.結果為U.
5. 以CTR模式,將IV最高字節設置為1,重新載入IV,然后加密明文緩存塊
6. 最后的結果,是輸出的密文塊加上U,都是16字節對齊的。
void Test_SSP_CCM_Encrypt (uint8 Mval, //認證域字節長度 [0,4,8,16]
uint8 *N, //指向13個字節的隨機數指針
uint8 *M, //指向待加密明文 (明文輸出也在這里,多加16個字節的空間)
uint16 len_m, //待加密明文長度
uint8 *AesKey, //AekKey密鑰指針
uint8 *Cstate) //明文的認證域內容
從目前淺顯的理解上來看,CCM的認證和加密好像是相互獨立設置的,從邏輯上,一段明文進來,先通過認證,產生一個tag,在后續加密時使用此Tag和IV生成一個新的校驗U.原負載明文填充滿后,通過CTR模式來加密數據,在密文的后面附上新的校驗碼U,這樣,就完成了校驗和加密的過程。
---------------今天就先介紹到這里,還有解密過程和代碼沒貼上來,周一來了再貼-----------------------
-------------------周一來了,整理剩下的代碼---------------------------------------------------
解密的過程和加密的相反,先解密,再解認證。
void Test_SSP_CCM_Decrypt (uint8 Mval, //認證域長度
uint8 *N, //隨機數
uint8 *C, //待解密密文指針
uint16 len_c, //待解密密文長度
uint8 *AesKey, //解密密鑰
uint8 *Cstate) //認證域內容
解密流程:
1. 先利用隨機數,構造A向量
2. 從待解密密文中提取最后Mval字節(補全16個字節)到U向量中
3. 通過OFB模式,來將U解密成T
4. 通過CTR模式,將密文解密成明文
5. 最后,將T附加在明文后
鑒權的過程是利用上述解密出來的明文,全場為len_c,認證域長度位為Mval,位置在字節的尾端,鑒權就是把解密的明文,通過(len_c-Mval)長度鑒權計算,把得到的結果和解密輸出的結果進行對比,如果相同,則鑒權成功,否則,鑒權失敗。
參考資料:openssl學習之ccm,gcm 模式