1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * AES (Rijndael) cipher - decrypt 3e5b75505Sopenharmony_ci * 4e5b75505Sopenharmony_ci * Modifications to public domain implementation: 5e5b75505Sopenharmony_ci * - cleanup 6e5b75505Sopenharmony_ci * - use C pre-processor to make it easier to change S table access 7e5b75505Sopenharmony_ci * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at 8e5b75505Sopenharmony_ci * cost of reduced throughput (quite small difference on Pentium 4, 9e5b75505Sopenharmony_ci * 10-25% when using -O1 or -O2 optimization) 10e5b75505Sopenharmony_ci * 11e5b75505Sopenharmony_ci * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> 12e5b75505Sopenharmony_ci * 13e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 14e5b75505Sopenharmony_ci * See README for more details. 15e5b75505Sopenharmony_ci */ 16e5b75505Sopenharmony_ci 17e5b75505Sopenharmony_ci#include "includes.h" 18e5b75505Sopenharmony_ci 19e5b75505Sopenharmony_ci#include "common.h" 20e5b75505Sopenharmony_ci#include "crypto.h" 21e5b75505Sopenharmony_ci#include "aes_i.h" 22e5b75505Sopenharmony_ci 23e5b75505Sopenharmony_ci/** 24e5b75505Sopenharmony_ci * Expand the cipher key into the decryption key schedule. 25e5b75505Sopenharmony_ci * 26e5b75505Sopenharmony_ci * @return the number of rounds for the given cipher key size. 27e5b75505Sopenharmony_ci */ 28e5b75505Sopenharmony_cistatic int rijndaelKeySetupDec(u32 rk[], const u8 cipherKey[], int keyBits) 29e5b75505Sopenharmony_ci{ 30e5b75505Sopenharmony_ci int Nr, i, j; 31e5b75505Sopenharmony_ci u32 temp; 32e5b75505Sopenharmony_ci 33e5b75505Sopenharmony_ci /* expand the cipher key: */ 34e5b75505Sopenharmony_ci Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); 35e5b75505Sopenharmony_ci if (Nr < 0) 36e5b75505Sopenharmony_ci return Nr; 37e5b75505Sopenharmony_ci /* invert the order of the round keys: */ 38e5b75505Sopenharmony_ci for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { 39e5b75505Sopenharmony_ci temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; 40e5b75505Sopenharmony_ci temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; 41e5b75505Sopenharmony_ci temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; 42e5b75505Sopenharmony_ci temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; 43e5b75505Sopenharmony_ci } 44e5b75505Sopenharmony_ci /* apply the inverse MixColumn transform to all round keys but the 45e5b75505Sopenharmony_ci * first and the last: */ 46e5b75505Sopenharmony_ci for (i = 1; i < Nr; i++) { 47e5b75505Sopenharmony_ci rk += 4; 48e5b75505Sopenharmony_ci for (j = 0; j < 4; j++) { 49e5b75505Sopenharmony_ci rk[j] = TD0_(TE4((rk[j] >> 24) )) ^ 50e5b75505Sopenharmony_ci TD1_(TE4((rk[j] >> 16) & 0xff)) ^ 51e5b75505Sopenharmony_ci TD2_(TE4((rk[j] >> 8) & 0xff)) ^ 52e5b75505Sopenharmony_ci TD3_(TE4((rk[j] ) & 0xff)); 53e5b75505Sopenharmony_ci } 54e5b75505Sopenharmony_ci } 55e5b75505Sopenharmony_ci 56e5b75505Sopenharmony_ci return Nr; 57e5b75505Sopenharmony_ci} 58e5b75505Sopenharmony_ci 59e5b75505Sopenharmony_civoid * aes_decrypt_init(const u8 *key, size_t len) 60e5b75505Sopenharmony_ci{ 61e5b75505Sopenharmony_ci u32 *rk; 62e5b75505Sopenharmony_ci int res; 63e5b75505Sopenharmony_ci rk = os_malloc(AES_PRIV_SIZE); 64e5b75505Sopenharmony_ci if (rk == NULL) 65e5b75505Sopenharmony_ci return NULL; 66e5b75505Sopenharmony_ci res = rijndaelKeySetupDec(rk, key, len * 8); 67e5b75505Sopenharmony_ci if (res < 0) { 68e5b75505Sopenharmony_ci os_free(rk); 69e5b75505Sopenharmony_ci return NULL; 70e5b75505Sopenharmony_ci } 71e5b75505Sopenharmony_ci rk[AES_PRIV_NR_POS] = res; 72e5b75505Sopenharmony_ci return rk; 73e5b75505Sopenharmony_ci} 74e5b75505Sopenharmony_ci 75e5b75505Sopenharmony_cistatic void rijndaelDecrypt(const u32 rk[/*44*/], int Nr, const u8 ct[16], 76e5b75505Sopenharmony_ci u8 pt[16]) 77e5b75505Sopenharmony_ci{ 78e5b75505Sopenharmony_ci u32 s0, s1, s2, s3, t0, t1, t2, t3; 79e5b75505Sopenharmony_ci#ifndef FULL_UNROLL 80e5b75505Sopenharmony_ci int r; 81e5b75505Sopenharmony_ci#endif /* ?FULL_UNROLL */ 82e5b75505Sopenharmony_ci 83e5b75505Sopenharmony_ci /* 84e5b75505Sopenharmony_ci * map byte array block to cipher state 85e5b75505Sopenharmony_ci * and add initial round key: 86e5b75505Sopenharmony_ci */ 87e5b75505Sopenharmony_ci s0 = GETU32(ct ) ^ rk[0]; 88e5b75505Sopenharmony_ci s1 = GETU32(ct + 4) ^ rk[1]; 89e5b75505Sopenharmony_ci s2 = GETU32(ct + 8) ^ rk[2]; 90e5b75505Sopenharmony_ci s3 = GETU32(ct + 12) ^ rk[3]; 91e5b75505Sopenharmony_ci 92e5b75505Sopenharmony_ci#define ROUND(i,d,s) \ 93e5b75505Sopenharmony_cid##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \ 94e5b75505Sopenharmony_cid##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \ 95e5b75505Sopenharmony_cid##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \ 96e5b75505Sopenharmony_cid##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3] 97e5b75505Sopenharmony_ci 98e5b75505Sopenharmony_ci#ifdef FULL_UNROLL 99e5b75505Sopenharmony_ci 100e5b75505Sopenharmony_ci ROUND(1,t,s); 101e5b75505Sopenharmony_ci ROUND(2,s,t); 102e5b75505Sopenharmony_ci ROUND(3,t,s); 103e5b75505Sopenharmony_ci ROUND(4,s,t); 104e5b75505Sopenharmony_ci ROUND(5,t,s); 105e5b75505Sopenharmony_ci ROUND(6,s,t); 106e5b75505Sopenharmony_ci ROUND(7,t,s); 107e5b75505Sopenharmony_ci ROUND(8,s,t); 108e5b75505Sopenharmony_ci ROUND(9,t,s); 109e5b75505Sopenharmony_ci if (Nr > 10) { 110e5b75505Sopenharmony_ci ROUND(10,s,t); 111e5b75505Sopenharmony_ci ROUND(11,t,s); 112e5b75505Sopenharmony_ci if (Nr > 12) { 113e5b75505Sopenharmony_ci ROUND(12,s,t); 114e5b75505Sopenharmony_ci ROUND(13,t,s); 115e5b75505Sopenharmony_ci } 116e5b75505Sopenharmony_ci } 117e5b75505Sopenharmony_ci 118e5b75505Sopenharmony_ci rk += Nr << 2; 119e5b75505Sopenharmony_ci 120e5b75505Sopenharmony_ci#else /* !FULL_UNROLL */ 121e5b75505Sopenharmony_ci 122e5b75505Sopenharmony_ci /* Nr - 1 full rounds: */ 123e5b75505Sopenharmony_ci r = Nr >> 1; 124e5b75505Sopenharmony_ci for (;;) { 125e5b75505Sopenharmony_ci ROUND(1,t,s); 126e5b75505Sopenharmony_ci rk += 8; 127e5b75505Sopenharmony_ci if (--r == 0) 128e5b75505Sopenharmony_ci break; 129e5b75505Sopenharmony_ci ROUND(0,s,t); 130e5b75505Sopenharmony_ci } 131e5b75505Sopenharmony_ci 132e5b75505Sopenharmony_ci#endif /* ?FULL_UNROLL */ 133e5b75505Sopenharmony_ci 134e5b75505Sopenharmony_ci#undef ROUND 135e5b75505Sopenharmony_ci 136e5b75505Sopenharmony_ci /* 137e5b75505Sopenharmony_ci * apply last round and 138e5b75505Sopenharmony_ci * map cipher state to byte array block: 139e5b75505Sopenharmony_ci */ 140e5b75505Sopenharmony_ci s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0]; 141e5b75505Sopenharmony_ci PUTU32(pt , s0); 142e5b75505Sopenharmony_ci s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1]; 143e5b75505Sopenharmony_ci PUTU32(pt + 4, s1); 144e5b75505Sopenharmony_ci s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2]; 145e5b75505Sopenharmony_ci PUTU32(pt + 8, s2); 146e5b75505Sopenharmony_ci s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3]; 147e5b75505Sopenharmony_ci PUTU32(pt + 12, s3); 148e5b75505Sopenharmony_ci} 149e5b75505Sopenharmony_ci 150e5b75505Sopenharmony_ci 151e5b75505Sopenharmony_ciint aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 152e5b75505Sopenharmony_ci{ 153e5b75505Sopenharmony_ci u32 *rk = ctx; 154e5b75505Sopenharmony_ci rijndaelDecrypt(ctx, rk[AES_PRIV_NR_POS], crypt, plain); 155e5b75505Sopenharmony_ci return 0; 156e5b75505Sopenharmony_ci} 157e5b75505Sopenharmony_ci 158e5b75505Sopenharmony_ci 159e5b75505Sopenharmony_civoid aes_decrypt_deinit(void *ctx) 160e5b75505Sopenharmony_ci{ 161e5b75505Sopenharmony_ci os_memset(ctx, 0, AES_PRIV_SIZE); 162e5b75505Sopenharmony_ci os_free(ctx); 163e5b75505Sopenharmony_ci} 164