In libgcrypt shared library, during AES encryption/decryption operation lookup tables are accessed. In case of AES encryption, 1KB lookup table ( defined as static const u32 encT inside shared library) and in case of AES decryption, 1KB + 256 Byte lookup table ( defined as
static const struct
{
u32 T[256];
byte inv_sbox[256];
} dec_tables inside shared library) are used.
Being a static member of shared library, where encT and dec_tables will be placed ? At code secion or any other section ?
when I check with nm command , it shows r , means read only.
nm /usr/local/lib/libgcrypt.so | grep encT
00091ae0 r encT
nm /usr/local/lib/libgcrypt.so | grep dec_tables
000915e0 r dec_tables
Is read-only section and code section are same with respect to shared library ?
I have made a sample program to perform AES decryption and to know what is the control flow of the program to perform AES decryption.
gcryError = gcry_cipher_decrypt(
gcryCipherHd, // gcry_cipher_hd_t
dec_out, // void *
txtLength, // size_t
enc_out, // const void *
txtLength); // size_t
Here is what I found ,
gcry_cipher_decrypt (visibility.c ) -->
_gcry_cipher_decrypt (cipher.c) -->
static cipher_decrypt (cipher.c) -->
static do_ecb_decrypt (cipher.c) -->
static do_ecb_crypt (cipher.c) -->
static do_decrypt (rijndael.c) -->
static do_decrypt_fn (rijndael.c)
Inside, do_decrypt_fn function final decryption operations are performed by accessing dec_tables.T and dec_tables.inv_sbox.
// few lines are added for reference
static unsigned int
do_decrypt_fn (const RIJNDAEL_context *ctx, unsigned char *b,
const unsigned char *a)
{
sb[3] ^= rol(decT[(byte)(sa[3] >> (0 * 8))], (0 * 8));
sa[0] ^= rol(decT[(byte)(sa[3] >> (1 * 8))], (1 * 8));
sa[1] ^= rol(decT[(byte)(sa[3] >> (2 * 8))], (2 * 8));
sa[2] ^= rol(decT[(byte)(sa[3] >> (3 * 8))], (3 * 8));
sa[3] = rk[1][3] ^ sb[3];
/* Last round is special. */
sb[0] = inv_sbox[(byte)(sa[0] >> (0 * 8))] << (0 * 8);
sb[1] = inv_sbox[(byte)(sa[0] >> (1 * 8))] << (1 * 8);
sb[2] = inv_sbox[(byte)(sa[0] >> (2 * 8))] << (2 * 8);
sb[3] = inv_sbox[(byte)(sa[0] >> (3 * 8))] << (3 * 8);
sa[0] = sb[0] ^ rk[0][0];
Here, dec_tables is defined inside rijndael-tables.h and this header file is included inside rijndael.c file.
static const struct
{
u32 T[256];
byte inv_sbox[256];
} dec_tables =
{
{
0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a,
0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b,
...},
{
0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
...}
#define decT dec_tables.T
#define inv_sbox dec_tables.inv_sbox
Here is my questions to you.
- Being a static type , all these static functions and static data dec_tables are not visible outside shared library module. Then how they are located to use in decryption?
I think this OFFSET of encT and dec_tables are used by some function or in some calculation to locate dec_tables to perform the AES decryption. Am I right ?
Can anyone explain using readelf/objdump/nm or other way, how shared library use these OFFSET to locate the static data (encT/dec_tables) used for AES encryption/decryption ?
Or
- is these OFFSET useful in any sense to locate encT/dec_tables static data ?
I don't know how GOT or PLT works with OFFSET . Is there any way to use these OFFSET with respect to GOT/PLT to locate these static data ?
I am using Ubuntu 16.06, gcc-4.9.
Any link/ sample program solve the above doubts will be great help. Thanks in advance.