1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * AES (Rijndael) cipher - encrypt 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_cistatic void rijndaelEncrypt(const u32 rk[], int Nr, const u8 pt[16], u8 ct[16]) 24e5b75505Sopenharmony_ci{ 25e5b75505Sopenharmony_ci u32 s0, s1, s2, s3, t0, t1, t2, t3; 26e5b75505Sopenharmony_ci#ifndef FULL_UNROLL 27e5b75505Sopenharmony_ci int r; 28e5b75505Sopenharmony_ci#endif /* ?FULL_UNROLL */ 29e5b75505Sopenharmony_ci 30e5b75505Sopenharmony_ci /* 31e5b75505Sopenharmony_ci * map byte array block to cipher state 32e5b75505Sopenharmony_ci * and add initial round key: 33e5b75505Sopenharmony_ci */ 34e5b75505Sopenharmony_ci s0 = GETU32(pt ) ^ rk[0]; 35e5b75505Sopenharmony_ci s1 = GETU32(pt + 4) ^ rk[1]; 36e5b75505Sopenharmony_ci s2 = GETU32(pt + 8) ^ rk[2]; 37e5b75505Sopenharmony_ci s3 = GETU32(pt + 12) ^ rk[3]; 38e5b75505Sopenharmony_ci 39e5b75505Sopenharmony_ci#define ROUND(i,d,s) \ 40e5b75505Sopenharmony_cid##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ 41e5b75505Sopenharmony_cid##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ 42e5b75505Sopenharmony_cid##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ 43e5b75505Sopenharmony_cid##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] 44e5b75505Sopenharmony_ci 45e5b75505Sopenharmony_ci#ifdef FULL_UNROLL 46e5b75505Sopenharmony_ci 47e5b75505Sopenharmony_ci ROUND(1,t,s); 48e5b75505Sopenharmony_ci ROUND(2,s,t); 49e5b75505Sopenharmony_ci ROUND(3,t,s); 50e5b75505Sopenharmony_ci ROUND(4,s,t); 51e5b75505Sopenharmony_ci ROUND(5,t,s); 52e5b75505Sopenharmony_ci ROUND(6,s,t); 53e5b75505Sopenharmony_ci ROUND(7,t,s); 54e5b75505Sopenharmony_ci ROUND(8,s,t); 55e5b75505Sopenharmony_ci ROUND(9,t,s); 56e5b75505Sopenharmony_ci if (Nr > 10) { 57e5b75505Sopenharmony_ci ROUND(10,s,t); 58e5b75505Sopenharmony_ci ROUND(11,t,s); 59e5b75505Sopenharmony_ci if (Nr > 12) { 60e5b75505Sopenharmony_ci ROUND(12,s,t); 61e5b75505Sopenharmony_ci ROUND(13,t,s); 62e5b75505Sopenharmony_ci } 63e5b75505Sopenharmony_ci } 64e5b75505Sopenharmony_ci 65e5b75505Sopenharmony_ci rk += Nr << 2; 66e5b75505Sopenharmony_ci 67e5b75505Sopenharmony_ci#else /* !FULL_UNROLL */ 68e5b75505Sopenharmony_ci 69e5b75505Sopenharmony_ci /* Nr - 1 full rounds: */ 70e5b75505Sopenharmony_ci r = Nr >> 1; 71e5b75505Sopenharmony_ci for (;;) { 72e5b75505Sopenharmony_ci ROUND(1,t,s); 73e5b75505Sopenharmony_ci rk += 8; 74e5b75505Sopenharmony_ci if (--r == 0) 75e5b75505Sopenharmony_ci break; 76e5b75505Sopenharmony_ci ROUND(0,s,t); 77e5b75505Sopenharmony_ci } 78e5b75505Sopenharmony_ci 79e5b75505Sopenharmony_ci#endif /* ?FULL_UNROLL */ 80e5b75505Sopenharmony_ci 81e5b75505Sopenharmony_ci#undef ROUND 82e5b75505Sopenharmony_ci 83e5b75505Sopenharmony_ci /* 84e5b75505Sopenharmony_ci * apply last round and 85e5b75505Sopenharmony_ci * map cipher state to byte array block: 86e5b75505Sopenharmony_ci */ 87e5b75505Sopenharmony_ci s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; 88e5b75505Sopenharmony_ci PUTU32(ct , s0); 89e5b75505Sopenharmony_ci s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; 90e5b75505Sopenharmony_ci PUTU32(ct + 4, s1); 91e5b75505Sopenharmony_ci s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; 92e5b75505Sopenharmony_ci PUTU32(ct + 8, s2); 93e5b75505Sopenharmony_ci s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; 94e5b75505Sopenharmony_ci PUTU32(ct + 12, s3); 95e5b75505Sopenharmony_ci} 96e5b75505Sopenharmony_ci 97e5b75505Sopenharmony_ci 98e5b75505Sopenharmony_civoid * aes_encrypt_init(const u8 *key, size_t len) 99e5b75505Sopenharmony_ci{ 100e5b75505Sopenharmony_ci u32 *rk; 101e5b75505Sopenharmony_ci int res; 102e5b75505Sopenharmony_ci 103e5b75505Sopenharmony_ci if (TEST_FAIL()) 104e5b75505Sopenharmony_ci return NULL; 105e5b75505Sopenharmony_ci 106e5b75505Sopenharmony_ci rk = os_malloc(AES_PRIV_SIZE); 107e5b75505Sopenharmony_ci if (rk == NULL) 108e5b75505Sopenharmony_ci return NULL; 109e5b75505Sopenharmony_ci res = rijndaelKeySetupEnc(rk, key, len * 8); 110e5b75505Sopenharmony_ci if (res < 0) { 111e5b75505Sopenharmony_ci os_free(rk); 112e5b75505Sopenharmony_ci return NULL; 113e5b75505Sopenharmony_ci } 114e5b75505Sopenharmony_ci rk[AES_PRIV_NR_POS] = res; 115e5b75505Sopenharmony_ci return rk; 116e5b75505Sopenharmony_ci} 117e5b75505Sopenharmony_ci 118e5b75505Sopenharmony_ci 119e5b75505Sopenharmony_ciint aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 120e5b75505Sopenharmony_ci{ 121e5b75505Sopenharmony_ci u32 *rk = ctx; 122e5b75505Sopenharmony_ci rijndaelEncrypt(ctx, rk[AES_PRIV_NR_POS], plain, crypt); 123e5b75505Sopenharmony_ci return 0; 124e5b75505Sopenharmony_ci} 125e5b75505Sopenharmony_ci 126e5b75505Sopenharmony_ci 127e5b75505Sopenharmony_civoid aes_encrypt_deinit(void *ctx) 128e5b75505Sopenharmony_ci{ 129e5b75505Sopenharmony_ci os_memset(ctx, 0, AES_PRIV_SIZE); 130e5b75505Sopenharmony_ci os_free(ctx); 131e5b75505Sopenharmony_ci} 132