0.引言算法
對於加密算法的軟件實現,一般已經有不少的成熟的庫可供選擇,只須要根據本身的要求進行選擇便可相應的庫便可(有的可能須要進行些許修改)。這裏選擇的是C語言實現的一個開源密碼庫mbedTLS,mbedTLS由XySSL發展而來,後改成PolarSSL,PolarSSL被ARM公司收購後改爲了mbedTLS,主要用於物聯網等安全嵌入式領域。mbedTLS實現了常見的分組加密算法、hash算法、RSA以及ECC公鑰密碼體制,一個適用於嵌入式的SSL協議以及X509證書等,基本可以知足大部分的嵌入式安全應用。安全
1.AES加密算法代碼分析數據結構
這裏再也不詳細的介紹AES的數學原理以及設計思路等,只是結合軟件進行代碼分析,關於AES的官方文檔能夠在NIST網站上下載獲得。函數
1)數據結構網站
數據結構與算法密切相關,一般分組加密算法定義的數據結構都較爲相似,mbedTLS的AES定義了以下數據結構:ui
typedef struct { int nr; /*!< number of rounds */ uint32_t *rk; /*!< AES round keys */ uint32_t buf[68]; /*!< unaligned data */ } mbedtls_aes_context;
2)算法主體加密
分組加密算法的軟件實現一般會採用「查找表」的方式來提升算法的運算速度,經過表格或者預計算表格直接查表獲得對應的算法運算結果。spa
對算法的分析僅僅以加密算法爲例,解密算法的過程基本相似,只是前向表格改成逆向表格而已。設計
下面先給出代碼再進行分析:code
1 void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, 2 const unsigned char input[16], 3 unsigned char output[16] ) 4 { 5 int i; 6 uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; 7 8 RK = ctx->rk; 9 10 GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; 11 GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; 12 GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; 13 GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; 14 15 for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) 16 { 17 AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); 18 AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); 19 } 20 21 AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); 22 23 X0 = *RK++ ^ \ 24 ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ 25 ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ 26 ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ 27 ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); 28 29 X1 = *RK++ ^ \ 30 ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ 31 ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ 32 ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ 33 ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); 34 35 X2 = *RK++ ^ \ 36 ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ 37 ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ 38 ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ 39 ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); 40 41 X3 = *RK++ ^ \ 42 ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ 43 ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ 44 ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ 45 ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); 46 47 PUT_UINT32_LE( X0, output, 0 ); 48 PUT_UINT32_LE( X1, output, 4 ); 49 PUT_UINT32_LE( X2, output, 8 ); 50 PUT_UINT32_LE( X3, output, 12 ); 51 }
分析能夠獲得算法的過程爲:
輪密鑰加->N-1輪輪變換->末輪變換
其中末輪變換隻有:字節置換(subbyte)/行移位(shiftrow)/輪密鑰加(addroundkey)
中間的輪變換則爲:字節置換(subbyte)/行移位(shiftrow)/列混合(mixcol)/輪密鑰加(addroundkey)
上述代碼中,RK爲輪密鑰,FSb爲S盒(Subbyte)的查找表,FTx則包括字節置換與列混合兩個過程,由於行移位爲線性變換,其運算過程能夠和列混合進行交換。
AES_ROUND由宏定義獲得,代碼以下:
1 #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ 2 { \ 3 X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ 4 FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ 5 FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ 6 FT3[ ( Y3 >> 24 ) & 0xFF ]; \ 7 \ 8 X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ 9 FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ 10 FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ 11 FT3[ ( Y0 >> 24 ) & 0xFF ]; \ 12 \ 13 X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ 14 FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ 15 FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ 16 FT3[ ( Y1 >> 24 ) & 0xFF ]; \ 17 \ 18 X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ 19 FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ 20 FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ 21 FT3[ ( Y2 >> 24 ) & 0xFF ]; \ 22 }
mbedTLS給出了兩種實現,1.ROM_TABLE的方式,全部表格直接給出,再也不一一列出各類表格;2.表格預計算的方式,因爲AES的設計是基於有限域的,表格預計算須要一些有限域的輔助函數,整個預計算的過程以下:
1 #define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) 2 #define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) 3 #define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) 4 5 static int aes_init_done = 0; 6 7 static void aes_gen_tables( void ) 8 { 9 int i, x, y, z; 10 int pow[256]; 11 int log[256]; 12 13 /* 14 * compute pow and log tables over GF(2^8) 15 */ 16 for( i = 0, x = 1; i < 256; i++ ) 17 { 18 pow[i] = x; 19 log[x] = i; 20 x = ( x ^ XTIME( x ) ) & 0xFF; 21 } 22 23 /* 24 * calculate the round constants 25 */ 26 for( i = 0, x = 1; i < 10; i++ ) 27 { 28 RCON[i] = (uint32_t) x; 29 x = XTIME( x ) & 0xFF; 30 } 31 32 /* 33 * generate the forward and reverse S-boxes 34 */ 35 FSb[0x00] = 0x63; 36 RSb[0x63] = 0x00; 37 38 for( i = 1; i < 256; i++ ) 39 { 40 x = pow[255 - log[i]]; 41 42 y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; 43 x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; 44 x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; 45 x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; 46 x ^= y ^ 0x63; 47 48 FSb[i] = (unsigned char) x; 49 RSb[x] = (unsigned char) i; 50 } 51 52 /* 53 * generate the forward and reverse tables 54 */ 55 for( i = 0; i < 256; i++ ) 56 { 57 x = FSb[i]; 58 y = XTIME( x ) & 0xFF; 59 z = ( y ^ x ) & 0xFF; 60 61 FT0[i] = ( (uint32_t) y ) ^ 62 ( (uint32_t) x << 8 ) ^ 63 ( (uint32_t) x << 16 ) ^ 64 ( (uint32_t) z << 24 ); 65 66 FT1[i] = ROTL8( FT0[i] ); 67 FT2[i] = ROTL8( FT1[i] ); 68 FT3[i] = ROTL8( FT2[i] ); 69 70 x = RSb[i]; 71 72 RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ 73 ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ 74 ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ 75 ( (uint32_t) MUL( 0x0B, x ) << 24 ); 76 77 RT1[i] = ROTL8( RT0[i] ); 78 RT2[i] = ROTL8( RT1[i] ); 79 RT3[i] = ROTL8( RT2[i] ); 80 } 81 }
在有限域運算中,使用了對數表的方式來實現有限域的乘法操做,這是AES設計者在提交算法是所提供的一種計算方式。
38~50行代碼進行有限域求逆算法(使用對數表),再進行仿射變換,求得S盒,同時能夠獲得逆向S盒。AES的S盒設計爲(A*x-1+b),A爲2進制矩陣,b爲2進制列向量(0x63)。
再計算FTx,FTx的計算須要有限域乘法操做,其乘法爲固定乘法操做,主要有x2與x3,(逆變換乘數爲0x0e,0x09,0x0d,0x0b)。其中有限域的乘法運算也是基於對數表完成的。
2.算法簡介
……