| 1 | /* rijndael-api-ref.c v2.1 April 2000 |
| 2 | * Reference ANSI C code |
| 3 | * authors: v2.0 Paulo Barreto |
| 4 | * Vincent Rijmen, K.U.Leuven |
| 5 | * v2.1 Vincent Rijmen, K.U.Leuven |
| 6 | * |
| 7 | * This code is placed in the public domain. |
| 8 | */ |
| 9 | #include "mvOs.h" |
| 10 | |
| 11 | #include "mvAes.h" |
| 12 | #include "mvAesAlg.h" |
| 13 | |
| 14 | |
| 15 | /* Defines: |
| 16 | Add any additional defines you need |
| 17 | */ |
| 18 | |
| 19 | #define MODE_ECB 1 /* Are we ciphering in ECB mode? */ |
| 20 | #define MODE_CBC 2 /* Are we ciphering in CBC mode? */ |
| 21 | #define MODE_CFB1 3 /* Are we ciphering in 1-bit CFB mode? */ |
| 22 | |
| 23 | |
| 24 | int aesMakeKey(MV_U8 *expandedKey, MV_U8 *keyMaterial, int keyLen, int blockLen) |
| 25 | { |
| 26 | MV_U8 W[MAXROUNDS+1][4][MAXBC]; |
| 27 | MV_U8 k[4][MAXKC]; |
| 28 | MV_U8 j; |
| 29 | int i, rounds, KC; |
| 30 | |
| 31 | if (expandedKey == NULL) |
| 32 | { |
| 33 | return AES_BAD_KEY_INSTANCE; |
| 34 | } |
| 35 | |
| 36 | if (!((keyLen == 128) || (keyLen == 192) || (keyLen == 256))) |
| 37 | { |
| 38 | return AES_BAD_KEY_MAT; |
| 39 | } |
| 40 | |
| 41 | if (keyMaterial == NULL) |
| 42 | { |
| 43 | return AES_BAD_KEY_MAT; |
| 44 | } |
| 45 | |
| 46 | /* initialize key schedule: */ |
| 47 | for(i=0; i<keyLen/8; i++) |
| 48 | { |
| 49 | j = keyMaterial[i]; |
| 50 | k[i % 4][i / 4] = j; |
| 51 | } |
| 52 | |
| 53 | rijndaelKeySched (k, keyLen, blockLen, W); |
| 54 | #ifdef MV_AES_DEBUG |
| 55 | { |
| 56 | MV_U8* pW = &W[0][0][0]; |
| 57 | int x; |
| 58 | |
| 59 | mvOsPrintf("Expended Key: size = %d\n", sizeof(W)); |
| 60 | for(i=0; i<sizeof(W); i++) |
| 61 | { |
| 62 | mvOsPrintf("%02x ", pW[i]); |
| 63 | } |
| 64 | for(i=0; i<MAXROUNDS+1; i++) |
| 65 | { |
| 66 | mvOsPrintf("\n Round #%02d: ", i); |
| 67 | for(x=0; x<MAXBC; x++) |
| 68 | { |
| 69 | mvOsPrintf("%02x%02x%02x%02x ", |
| 70 | W[i][0][x], W[i][1][x], W[i][2][x], W[i][3][x]); |
| 71 | } |
| 72 | mvOsPrintf("\n"); |
| 73 | } |
| 74 | } |
| 75 | #endif /* MV_AES_DEBUG */ |
| 76 | switch (keyLen) |
| 77 | { |
| 78 | case 128: |
| 79 | rounds = 10; |
| 80 | KC = 4; |
| 81 | break; |
| 82 | case 192: |
| 83 | rounds = 12; |
| 84 | KC = 6; |
| 85 | break; |
| 86 | case 256: |
| 87 | rounds = 14; |
| 88 | KC = 8; |
| 89 | break; |
| 90 | default : |
| 91 | return (-1); |
| 92 | } |
| 93 | |
| 94 | for(i=0; i<MAXBC; i++) |
| 95 | { |
| 96 | for(j=0; j<4; j++) |
| 97 | { |
| 98 | expandedKey[i*4+j] = W[rounds][j][i]; |
| 99 | } |
| 100 | } |
| 101 | for(; i<KC; i++) |
| 102 | { |
| 103 | for(j=0; j<4; j++) |
| 104 | { |
| 105 | expandedKey[i*4+j] = W[rounds-1][j][i+MAXBC-KC]; |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | |
| 110 | return 0; |
| 111 | } |
| 112 | |
| 113 | int aesBlockEncrypt128(MV_U8 mode, MV_U8 *IV, MV_U8 *expandedKey, int keyLen, |
| 114 | MV_U32 *plain, int numBlocks, MV_U32 *cipher) |
| 115 | { |
| 116 | int i, j, t; |
| 117 | MV_U8 block[4][MAXBC]; |
| 118 | int rounds; |
| 119 | char *input, *outBuffer; |
| 120 | |
| 121 | input = (char*)plain; |
| 122 | outBuffer = (char*)cipher; |
| 123 | |
| 124 | /* check parameter consistency: */ |
| 125 | if( (expandedKey == NULL) || ((keyLen != 128) && (keyLen != 192) && (keyLen != 256))) |
| 126 | { |
| 127 | return AES_BAD_KEY_MAT; |
| 128 | } |
| 129 | if ((mode != MODE_ECB && mode != MODE_CBC)) |
| 130 | { |
| 131 | return AES_BAD_CIPHER_STATE; |
| 132 | } |
| 133 | |
| 134 | switch (keyLen) |
| 135 | { |
| 136 | case 128: rounds = 10; break; |
| 137 | case 192: rounds = 12; break; |
| 138 | case 256: rounds = 14; break; |
| 139 | default : return (-3); /* this cannot happen */ |
| 140 | } |
| 141 | |
| 142 | |
| 143 | switch (mode) |
| 144 | { |
| 145 | case MODE_ECB: |
| 146 | for (i = 0; i < numBlocks; i++) |
| 147 | { |
| 148 | for (j = 0; j < 4; j++) |
| 149 | { |
| 150 | for(t = 0; t < 4; t++) |
| 151 | /* parse input stream into rectangular array */ |
| 152 | block[t][j] = input[16*i+4*j+t] & 0xFF; |
| 153 | } |
| 154 | rijndaelEncrypt128(block, (MV_U8 (*)[4][MAXBC])expandedKey, rounds); |
| 155 | for (j = 0; j < 4; j++) |
| 156 | { |
| 157 | /* parse rectangular array into output ciphertext bytes */ |
| 158 | for(t = 0; t < 4; t++) |
| 159 | outBuffer[16*i+4*j+t] = (MV_U8) block[t][j]; |
| 160 | |
| 161 | } |
| 162 | } |
| 163 | break; |
| 164 | |
| 165 | case MODE_CBC: |
| 166 | for (j = 0; j < 4; j++) |
| 167 | { |
| 168 | for(t = 0; t < 4; t++) |
| 169 | /* parse initial value into rectangular array */ |
| 170 | block[t][j] = IV[t+4*j] & 0xFF; |
| 171 | } |
| 172 | for (i = 0; i < numBlocks; i++) |
| 173 | { |
| 174 | for (j = 0; j < 4; j++) |
| 175 | { |
| 176 | for(t = 0; t < 4; t++) |
| 177 | /* parse input stream into rectangular array and exor with |
| 178 | IV or the previous ciphertext */ |
| 179 | block[t][j] ^= input[16*i+4*j+t] & 0xFF; |
| 180 | } |
| 181 | rijndaelEncrypt128(block, (MV_U8 (*)[4][MAXBC])expandedKey, rounds); |
| 182 | for (j = 0; j < 4; j++) |
| 183 | { |
| 184 | /* parse rectangular array into output ciphertext bytes */ |
| 185 | for(t = 0; t < 4; t++) |
| 186 | outBuffer[16*i+4*j+t] = (MV_U8) block[t][j]; |
| 187 | } |
| 188 | } |
| 189 | break; |
| 190 | |
| 191 | default: return AES_BAD_CIPHER_STATE; |
| 192 | } |
| 193 | |
| 194 | return 0; |
| 195 | } |
| 196 | |
| 197 | int aesBlockDecrypt128(MV_U8 mode, MV_U8 *IV, MV_U8 *expandedKey, int keyLen, |
| 198 | MV_U32 *srcData, int numBlocks, MV_U32 *dstData) |
| 199 | { |
| 200 | int i, j, t; |
| 201 | MV_U8 block[4][MAXBC]; |
| 202 | MV_U8 iv[4][MAXBC]; |
| 203 | int rounds; |
| 204 | char *input, *outBuffer; |
| 205 | |
| 206 | input = (char*)srcData; |
| 207 | outBuffer = (char*)dstData; |
| 208 | |
| 209 | if (expandedKey == NULL) |
| 210 | { |
| 211 | return AES_BAD_KEY_MAT; |
| 212 | } |
| 213 | |
| 214 | /* check parameter consistency: */ |
| 215 | if (keyLen != 128 && keyLen != 192 && keyLen != 256) |
| 216 | { |
| 217 | return AES_BAD_KEY_MAT; |
| 218 | } |
| 219 | if ((mode != MODE_ECB && mode != MODE_CBC)) |
| 220 | { |
| 221 | return AES_BAD_CIPHER_STATE; |
| 222 | } |
| 223 | |
| 224 | switch (keyLen) |
| 225 | { |
| 226 | case 128: rounds = 10; break; |
| 227 | case 192: rounds = 12; break; |
| 228 | case 256: rounds = 14; break; |
| 229 | default : return (-3); /* this cannot happen */ |
| 230 | } |
| 231 | |
| 232 | |
| 233 | switch (mode) |
| 234 | { |
| 235 | case MODE_ECB: |
| 236 | for (i = 0; i < numBlocks; i++) |
| 237 | { |
| 238 | for (j = 0; j < 4; j++) |
| 239 | { |
| 240 | for(t = 0; t < 4; t++) |
| 241 | { |
| 242 | /* parse input stream into rectangular array */ |
| 243 | block[t][j] = input[16*i+4*j+t] & 0xFF; |
| 244 | } |
| 245 | } |
| 246 | rijndaelDecrypt128(block, (MV_U8 (*)[4][MAXBC])expandedKey, rounds); |
| 247 | for (j = 0; j < 4; j++) |
| 248 | { |
| 249 | /* parse rectangular array into output ciphertext bytes */ |
| 250 | for(t = 0; t < 4; t++) |
| 251 | outBuffer[16*i+4*j+t] = (MV_U8) block[t][j]; |
| 252 | } |
| 253 | } |
| 254 | break; |
| 255 | |
| 256 | case MODE_CBC: |
| 257 | /* first block */ |
| 258 | for (j = 0; j < 4; j++) |
| 259 | { |
| 260 | for(t = 0; t < 4; t++) |
| 261 | { |
| 262 | /* parse input stream into rectangular array */ |
| 263 | block[t][j] = input[4*j+t] & 0xFF; |
| 264 | iv[t][j] = block[t][j]; |
| 265 | } |
| 266 | } |
| 267 | rijndaelDecrypt128(block, (MV_U8 (*)[4][MAXBC])expandedKey, rounds); |
| 268 | |
| 269 | for (j = 0; j < 4; j++) |
| 270 | { |
| 271 | /* exor the IV and parse rectangular array into output ciphertext bytes */ |
| 272 | for(t = 0; t < 4; t++) |
| 273 | { |
| 274 | outBuffer[4*j+t] = (MV_U8) (block[t][j] ^ IV[t+4*j]); |
| 275 | IV[t+4*j] = iv[t][j]; |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | /* next blocks */ |
| 280 | for (i = 1; i < numBlocks; i++) |
| 281 | { |
| 282 | for (j = 0; j < 4; j++) |
| 283 | { |
| 284 | for(t = 0; t < 4; t++) |
| 285 | { |
| 286 | /* parse input stream into rectangular array */ |
| 287 | iv[t][j] = input[16*i+4*j+t] & 0xFF; |
| 288 | block[t][j] = iv[t][j]; |
| 289 | } |
| 290 | } |
| 291 | rijndaelDecrypt128(block, (MV_U8 (*)[4][MAXBC])expandedKey, rounds); |
| 292 | |
| 293 | for (j = 0; j < 4; j++) |
| 294 | { |
| 295 | /* exor previous ciphertext block and parse rectangular array |
| 296 | into output ciphertext bytes */ |
| 297 | for(t = 0; t < 4; t++) |
| 298 | { |
| 299 | outBuffer[16*i+4*j+t] = (MV_U8) (block[t][j] ^ IV[t+4*j]); |
| 300 | IV[t+4*j] = iv[t][j]; |
| 301 | } |
| 302 | } |
| 303 | } |
| 304 | break; |
| 305 | |
| 306 | default: return AES_BAD_CIPHER_STATE; |
| 307 | } |
| 308 | |
| 309 | return 0; |
| 310 | } |
| 311 | |
| 312 | |
| 313 | |