• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 #include "hitls_build.h"
16 #if defined(HITLS_CRYPTO_AES) && !defined(HITLS_CRYPTO_AES_PRECALC_TABLES)
17 
18 #include "securec.h"
19 #include "bsl_err_internal.h"
20 #include "crypt_utils.h"
21 #include "crypt_errno.h"
22 #include "bsl_sal.h"
23 #include "crypt_aes.h"
24 #include "crypt_aes_sbox.h"
25 
26 #define BYTE_BITS 8
27 
28 static const uint8_t AES_S[256] = {
29     0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, 0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U,
30     0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U, 0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U,
31     0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU, 0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U,
32     0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU, 0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U,
33     0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U, 0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U,
34     0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU, 0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU,
35     0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U, 0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U,
36     0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U, 0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U,
37     0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U, 0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U,
38     0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U, 0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU,
39     0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU, 0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U,
40     0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U, 0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U,
41     0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U, 0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU,
42     0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU, 0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU,
43     0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U, 0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU,
44     0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U, 0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U
45 };
46 
47 #define SEARCH_SBOX(t)                                                                                  \
48     ((AES_S[((t) >> 24)] << 24) | (AES_S[((t) >> 16) & 0xFF] << 16) | (AES_S[((t) >> 8) & 0xFF] << 8) | \
49         (AES_S[((t) >> 0) & 0xFF] << 0))
50 
51 #define SEARCH_INVSBOX(t)                                                                                              \
52     ((InvSubSbox(((t) >> 24)) << 24) | (InvSubSbox(((t) >> 16) & 0xFF) << 16) | (InvSubSbox(((t) >> 8) & 0xFF) << 8) | \
53         (InvSubSbox(((t) >> 0) & 0xFF) << 0))
54 
SetAesKeyExpansionSbox(CRYPT_AES_Key * ctx,uint32_t keyLenBits,const uint8_t * key)55 void SetAesKeyExpansionSbox(CRYPT_AES_Key *ctx, uint32_t keyLenBits, const uint8_t *key)
56 {
57     uint32_t *ekey = ctx->key;
58     uint32_t keyLenByte = keyLenBits / (sizeof(uint32_t) * BYTE_BITS);
59     uint32_t i = 0;
60     for (i = 0; i < keyLenByte; ++i) {
61         ekey[i] = GET_UINT32_BE(key, i * sizeof(uint32_t));
62     }
63 
64     for (; i < 4 * (ctx->rounds + 1); ++i) {
65         if ((i % keyLenByte) == 0) {
66             ekey[i] = ekey[i - keyLenByte] ^ SEARCH_SBOX(ROTL32(ekey[i - 1], BYTE_BITS)) ^
67                 RoundConstArray(i / keyLenByte - 1);
68         } else if (keyLenByte > 6 && (i % keyLenByte) == 4) {
69             ekey[i] = ekey[i - keyLenByte] ^ SEARCH_SBOX(ekey[i - 1]);
70         } else {
71             ekey[i] = ekey[i - keyLenByte] ^ ekey[i - 1];
72         }
73     }
74 }
75 
AesAddRoundKey(uint32_t * state,const uint32_t * round,int nr)76 static void AesAddRoundKey(uint32_t *state, const uint32_t *round, int nr)
77 {
78     for (int i = 0; i < 4; ++i) {
79         state[i] ^= round[4 * nr + i];
80     }
81 }
82 
AesSubBytes(uint32_t * state)83 static void AesSubBytes(uint32_t *state)
84 {
85     for (int i = 0; i < 4; ++i) {
86         state[i] = SEARCH_SBOX(state[i]);
87     }
88 }
89 
AesShiftRows(uint32_t * state)90 static void AesShiftRows(uint32_t *state)
91 {
92     uint32_t s[4] = {0};
93     for (int32_t i = 0; i < 4; ++i) {
94         s[i] = state[i];
95     }
96 
97     state[0] = (s[0] & 0xFF000000) | (s[1] & 0xFF0000) | (s[2] & 0xFF00) | (s[3] & 0xFF);
98     state[1] = (s[1] & 0xFF000000) | (s[2] & 0xFF0000) | (s[3] & 0xFF00) | (s[0] & 0xFF);
99     state[2] = (s[2] & 0xFF000000) | (s[3] & 0xFF0000) | (s[0] & 0xFF00) | (s[1] & 0xFF);
100     state[3] = (s[3] & 0xFF000000) | (s[0] & 0xFF0000) | (s[1] & 0xFF00) | (s[2] & 0xFF);
101 }
102 
AesXtime(uint8_t x)103 static uint8_t AesXtime(uint8_t x)
104 {
105     return ((x << 1) ^ (((x >> 7) & 1) * 0x1b));
106 }
107 
AesXtimes(uint8_t x,int ts)108 static uint8_t AesXtimes(uint8_t x, int ts)
109 {
110     uint8_t tmpX = x;
111     int tmpTs = ts;
112     while (tmpTs-- > 0) {
113         tmpX = AesXtime(tmpX);
114     }
115 
116     return tmpX;
117 }
118 
AesMul(uint8_t x,uint8_t y)119 static uint8_t AesMul(uint8_t x, uint8_t y)
120 {
121     return ((((y >> 0) & 1) * AesXtimes(x, 0)) ^ (((y >> 1) & 1) * AesXtimes(x, 1)) ^
122         (((y >> 2) & 1) * AesXtimes(x, 2)) ^ (((y >> 3) & 1) * AesXtimes(x, 3)) ^ (((y >> 4) & 1) * AesXtimes(x, 4)) ^
123         (((y >> 5) & 1) * AesXtimes(x, 5)) ^ (((y >> 6) & 1) * AesXtimes(x, 6)) ^ (((y >> 7) & 1) * AesXtimes(x, 7)));
124 }
125 
AesMixColumns(uint32_t * state,bool isMixColumns)126 static void AesMixColumns(uint32_t *state, bool isMixColumns)
127 {
128     uint8_t ts[16] = {0};
129     for (int32_t i = 0; i < 4; ++i) {
130         PUT_UINT32_BE(state[i], ts, 4 * i);
131     }
132 
133     uint8_t aesY[16] = {2, 3, 1, 1, 1, 2, 3, 1, 1, 1, 2, 3, 3, 1, 1, 2};
134     uint8_t aesInvY[16] = {0x0e, 0x0b, 0x0d, 0x09, 0x09, 0x0e, 0x0b, 0x0d, 0x0d, 0x09, 0x0e, 0x0b, 0x0b, 0x0d, 0x09,
135                            0x0e};
136     uint8_t s[4];
137     uint8_t *y = isMixColumns == true ? aesY : aesInvY;
138 
139     for (int i = 0; i < 4; ++i) {
140         for (int r = 0; r < 4; ++r) {
141             s[r] = 0;
142             for (int j = 0; j < 4; ++j) {
143                 s[r] = s[r] ^ AesMul(ts[i * 4 + j], y[r * 4 + j]);
144             }
145         }
146         for (int r = 0; r < 4; ++r) {
147             ts[i * 4 + r] = s[r];
148         }
149     }
150 
151     for (int32_t i = 0; i < 4; ++i) {
152         state[i] = GET_UINT32_BE(ts, 4 * i);
153     }
154 }
155 
156 // addRound + 9/11/13 * (sub + shiftRow + mix + addRound) + (sub + shiftRow + addRound)
CRYPT_AES_EncryptSbox(const CRYPT_AES_Key * ctx,const uint8_t * in,uint8_t * out,uint32_t len)157 void CRYPT_AES_EncryptSbox(const CRYPT_AES_Key *ctx, const uint8_t *in, uint8_t *out, uint32_t len)
158 {
159     (void)len;
160     uint32_t s[4] = {0};
161 
162     for (int32_t i = 0; i < 4; ++i) {
163         s[i] = GET_UINT32_BE(in, 4 * i);
164     }
165     uint32_t nr = 0;
166     AesAddRoundKey(s, ctx->key, nr);
167     for (nr = 1; nr < ctx->rounds; ++nr) {
168         AesSubBytes(s);
169         AesShiftRows(s);
170         AesMixColumns(s, true);
171         AesAddRoundKey(s, ctx->key, nr);
172     }
173     AesSubBytes(s);
174     AesShiftRows(s);
175     AesAddRoundKey(s, ctx->key, nr);
176 
177     for (int32_t i = 0; i < 4; ++i) {
178         PUT_UINT32_BE(s[i], out, 4 * i);
179     }
180 }
181 
InvShiftRows(uint32_t * state)182 static void InvShiftRows(uint32_t *state)
183 {
184     uint32_t s[4] = {0};
185     for (int32_t i = 0; i < 4; ++i) {
186         s[i] = state[i];
187     }
188 
189     state[0] = (s[0] & 0xFF000000) | (s[3] & 0xFF0000) | (s[2] & 0xFF00) | (s[1] & 0xFF);
190     state[1] = (s[1] & 0xFF000000) | (s[0] & 0xFF0000) | (s[3] & 0xFF00) | (s[2] & 0xFF);
191     state[2] = (s[2] & 0xFF000000) | (s[1] & 0xFF0000) | (s[0] & 0xFF00) | (s[3] & 0xFF);
192     state[3] = (s[3] & 0xFF000000) | (s[2] & 0xFF0000) | (s[1] & 0xFF00) | (s[0] & 0xFF);
193 }
194 
InvSubBytes(uint32_t * state)195 static void InvSubBytes(uint32_t *state)
196 {
197     for (int i = 0; i < 4; ++i) {
198         state[i] = SEARCH_INVSBOX(state[i]);
199     }
200 }
201 
202 // (addRound + InvShiftRow + InvSub) + 9/11/13 * (addRound + invMix + InvShiftRow + InvSub) + addRound
CRYPT_AES_DecryptSbox(const CRYPT_AES_Key * ctx,const uint8_t * in,uint8_t * out,uint32_t len)203 void CRYPT_AES_DecryptSbox(const CRYPT_AES_Key *ctx, const uint8_t *in, uint8_t *out, uint32_t len)
204 {
205     (void)len;
206     uint32_t s[4] = {0};
207 
208     for (int32_t i = 0; i < 4; ++i) {
209         s[i] = GET_UINT32_BE(in, 4 * i);
210     }
211 
212     uint32_t nr = ctx->rounds;
213     AesAddRoundKey(s, ctx->key, nr);
214     InvShiftRows(s);
215     InvSubBytes(s);
216     for (nr = ctx->rounds - 1; nr > 0; --nr) {
217         AesAddRoundKey(s, ctx->key, nr);
218         AesMixColumns(s, false);
219         InvShiftRows(s);
220         InvSubBytes(s);
221     }
222     AesAddRoundKey(s, ctx->key, nr);
223     for (int32_t i = 0; i < 4; ++i) {
224         PUT_UINT32_BE(s[i], out, 4 * i);
225     }
226     BSL_SAL_CleanseData(&s, 4 * sizeof(uint32_t));
227 }
228 #endif /* HITLS_CRYPTO_AES && !HITLS_CRYPTO_AES_PRECALC_TABLES */