/* This file was automatically imported with
import_gcry.py. Please don't modify it */
GRUB_MOD_LICENSE ("GPLv3+");
/* Rijndael (AES) for GnuPG
* Copyright (C) 2000, 2001, 2002, 2003, 2007,
* 2008 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*******************************************************************
* The code here is based on the optimized implementation taken from
* http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ on Oct 2, 2000,
* which carries this notice:
*------------------------------------------
* rijndael-alg-fst.c v2.3 April '2000
*
* Optimised ANSI C code
*
* authors: v1.0: Antoon Bosselaers
* v2.0: Vincent Rijmen
* v2.3: Paulo Barreto
*
* This code is placed in the public domain.
*------------------------------------------
*
* The SP800-38a document is available at:
*
*/
#include "types.h" /* for byte and u32 typedefs */
#include "g10lib.h"
#include "cipher.h"
/* USE_PADLOCK indicates whether to compile the padlock specific
code. */
#ifdef ENABLE_PADLOCK_SUPPORT
# define USE_PADLOCK
# endif
#endif /*ENABLE_PADLOCK_SUPPORT*/
typedef struct
{
#ifdef USE_PADLOCK
/* The key as passed to the padlock engine. */
#endif
union
{
} u1;
union
{
} u2;
/* All the numbers. */
#include "rijndael-tables.h"
/* Perform the key setup. */
static gcry_err_code_t
{
static int initialized = 0;
static const char *selftest_failed=0;
int ROUNDS;
int i,j, r, t, rconpointer = 0;
int KC;
union
{
} k;
#define k k.k
union
{
} tk;
/* The on-the-fly self tests are only run in non-fips mode. In fips
mode explicit self-tests are required. Actually the on-the-fly
self-tests are not fully thread-safe and it might happen that a
failed self-test won't get noticed in another thread.
FIXME: We might want to have a central registry of succeeded
self-tests. */
if (!fips_mode () && !initialized)
{
initialized = 1;
selftest_failed = selftest ();
if (selftest_failed)
}
if (selftest_failed)
return GPG_ERR_SELFTEST_FAILED;
ctx->decryption_prepared = 0;
#ifdef USE_PADLOCK
ctx->use_padlock = 0;
#endif
{
ROUNDS = 10;
KC = 4;
#ifdef USE_PADLOCK
if ((_gcry_get_hw_features () & HWF_PADLOCK_AES))
{
}
#endif
}
{
ROUNDS = 12;
KC = 6;
}
{
ROUNDS = 14;
KC = 8;
}
else
return GPG_ERR_INV_KEYLEN;
#ifdef USE_PADLOCK
if (ctx->use_padlock)
{
/* Nothing to do as we support only hardware key generation for
now. */
}
else
#endif /*USE_PADLOCK*/
{
for (i = 0; i < (int)keylen; i++)
{
}
for (j = KC-1; j >= 0; j--)
{
}
r = 0;
t = 0;
/* Copy values into round key array. */
{
for (; (j < KC) && (t < 4); j++, t++)
{
}
if (t == 4)
{
r++;
t = 0;
}
}
while (r < ROUNDS + 1)
{
/* While not enough round key material calculated calculate
new values. */
if (KC != 8)
{
for (j = 1; j < KC; j++)
{
}
}
else
{
{
}
{
}
}
/* Copy values into round key array. */
{
for (; (j < KC) && (t < 4); j++, t++)
{
}
if (t == 4)
{
r++;
t = 0;
}
}
}
#undef W
}
return 0;
#undef k
}
static gcry_err_code_t
{
return rc;
}
/* Make a decryption key from an encryption key. */
static void
{
int r;
union
{
byte *w;
} w;
#define w w.w
for (r=0; r < MAXROUNDS+1; r++ )
{
}
{
w = W[r][0];
w = W[r][1];
w = W[r][2];
w = W[r][3];
}
#undef W
#undef w
}
/* Encrypt one block. A and B need to be aligned on a 4 byte
boundary. A and B may be the same. */
static void
unsigned char *b, const unsigned char *a)
{
int r;
union
{
} u;
{
}
/* Last round is special. */
}
static void
{
/* BX and AX are not necessary correctly aligned. Thus we need to
copy them here. */
union
{
byte a[16];
} a;
union
{
byte b[16];
} b;
do_encrypt_aligned (ctx, b.b, a.a);
}
/* Encrypt or decrypt one block using the padlock engine. A and B may
be the same. */
#ifdef USE_PADLOCK
static void
{
/* BX and AX are not necessary correctly aligned. Thus we need to
copy them here. */
/* The control word fields are:
127:12 11:10 9 8 7 6 5 4 3:0
RESERVED KSIZE CRYPT INTER KEYGN CIPHR ALIGN DGEST ROUND */
cword[1] = 0;
cword[2] = 0;
cword[3] = 0;
if (decrypt_flag)
cword[0] |= 0x00000200;
asm volatile
("pushfl\n\t" /* Force key reload. */
"popfl\n\t"
"xchg %3, %%ebx\n\t" /* Load key. */
"movl $1, %%ecx\n\t" /* Init counter for just one block. */
".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t" /* REP XSTORE ECB. */
"xchg %3, %%ebx\n" /* Restore GOT register. */
: /* No output */
: "%ecx", "cc", "memory"
);
}
#endif /*USE_PADLOCK*/
static void
{
#ifdef USE_PADLOCK
if (ctx->use_padlock)
{
do_padlock (ctx, 0, b, a);
}
else
#endif /*USE_PADLOCK*/
{
do_encrypt (ctx, b, a);
}
}
/* Bulk encryption of complete blocks in CFB mode. Caller needs to
make sure that IV is aligned on an unsigned long boundary. This
function is only intended for the bulk encryption feature of
cipher.c. */
/* Bulk encryption of complete blocks in CBC mode. Caller needs to
make sure that IV is aligned on an unsigned long boundary. This
function is only intended for the bulk encryption feature of
cipher.c. */
/* Decrypt one block. A and B need to be aligned on a 4 byte boundary
and the decryption must have been prepared. A and B may be the
same. */
static void
unsigned char *b, const unsigned char *a)
{
int r;
union
{
} u;
{
}
/* Last round is special. */
}
/* Decrypt one block. AX and BX may be the same. */
static void
{
/* BX and AX are not necessary correctly aligned. Thus we need to
copy them here. */
union
{
byte a[16];
} a;
union
{
byte b[16];
} b;
if ( !ctx->decryption_prepared )
{
prepare_decryption ( ctx );
_gcry_burn_stack (64);
}
do_decrypt_aligned (ctx, b.b, a.a);
}
static void
{
#ifdef USE_PADLOCK
if (ctx->use_padlock)
{
}
else
#endif /*USE_PADLOCK*/
{
do_decrypt (ctx, b, a);
}
}
/* Bulk decryption of complete blocks in CFB mode. Caller needs to
make sure that IV is aligned on an unisgned lonhg boundary. This
function is only intended for the bulk encryption feature of
cipher.c. */
/* Bulk decryption of complete blocks in CBC mode. Caller needs to
make sure that IV is aligned on an unsigned long boundary. This
function is only intended for the bulk encryption feature of
cipher.c. */
/* Run the self-tests for AES 128. Returns NULL on success. */
/* Run the self-tests for AES 192. Returns NULL on success. */
/* Run the self-tests for AES 256. Returns NULL on success. */
/* Run all the self-tests and return NULL on success. This function
is used for the on-the-fly self-tests. */
/* SP800-38a.pdf for AES-128. */
/* Complete selftest for AES-128 with all modes and driver code. */
/* Complete selftest for AES-192. */
/* Complete selftest for AES-256. */
/* Run a full self-test for ALGO and return 0 on success. */
static const char *rijndael_names[] =
{
"RIJNDAEL",
"AES128",
"AES-128",
};
{
{ "2.16.840.1.101.3.4.1.1", GCRY_CIPHER_MODE_ECB },
{ "2.16.840.1.101.3.4.1.2", GCRY_CIPHER_MODE_CBC },
{ "2.16.840.1.101.3.4.1.3", GCRY_CIPHER_MODE_OFB },
{ "2.16.840.1.101.3.4.1.4", GCRY_CIPHER_MODE_CFB },
{ NULL }
};
{
,
#ifdef GRUB_UTIL
.modname = "gcry_rijndael",
#endif
};
static const char *rijndael192_names[] =
{
"RIJNDAEL192",
"AES-192",
};
{
{ "2.16.840.1.101.3.4.1.21", GCRY_CIPHER_MODE_ECB },
{ "2.16.840.1.101.3.4.1.22", GCRY_CIPHER_MODE_CBC },
{ "2.16.840.1.101.3.4.1.23", GCRY_CIPHER_MODE_OFB },
{ "2.16.840.1.101.3.4.1.24", GCRY_CIPHER_MODE_CFB },
{ NULL }
};
{
,
#ifdef GRUB_UTIL
.modname = "gcry_rijndael",
#endif
};
static const char *rijndael256_names[] =
{
"RIJNDAEL256",
"AES-256",
};
{
{ "2.16.840.1.101.3.4.1.41", GCRY_CIPHER_MODE_ECB },
{ "2.16.840.1.101.3.4.1.42", GCRY_CIPHER_MODE_CBC },
{ "2.16.840.1.101.3.4.1.43", GCRY_CIPHER_MODE_OFB },
{ "2.16.840.1.101.3.4.1.44", GCRY_CIPHER_MODE_CFB },
{ NULL }
};
{
sizeof (RIJNDAEL_context),
,
#ifdef GRUB_UTIL
.modname = "gcry_rijndael",
#endif
};
{
}
{
}