aboutsummaryrefslogtreecommitdiff
path: root/src/lib/crypto/builtin/aes
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/crypto/builtin/aes')
-rw-r--r--src/lib/crypto/builtin/aes/Makefile.in61
-rw-r--r--src/lib/crypto/builtin/aes/aes-gen.c326
-rw-r--r--src/lib/crypto/builtin/aes/aes.h97
-rw-r--r--src/lib/crypto/builtin/aes/aes.txt70
-rw-r--r--src/lib/crypto/builtin/aes/aes_s2k.c90
-rw-r--r--src/lib/crypto/builtin/aes/aes_s2k.h4
-rw-r--r--src/lib/crypto/builtin/aes/aescpp.h55
-rw-r--r--src/lib/crypto/builtin/aes/aescrypp.c487
-rw-r--r--src/lib/crypto/builtin/aes/aescrypt.asm402
-rw-r--r--src/lib/crypto/builtin/aes/aescrypt.c421
-rw-r--r--src/lib/crypto/builtin/aes/aeskey.c369
-rw-r--r--src/lib/crypto/builtin/aes/aeskeypp.c399
-rw-r--r--src/lib/crypto/builtin/aes/aesopt.h851
-rw-r--r--src/lib/crypto/builtin/aes/aessrc.url1
-rw-r--r--src/lib/crypto/builtin/aes/aestab.c494
-rw-r--r--src/lib/crypto/builtin/aes/deps21
-rw-r--r--src/lib/crypto/builtin/aes/uitypes.h83
17 files changed, 4231 insertions, 0 deletions
diff --git a/src/lib/crypto/builtin/aes/Makefile.in b/src/lib/crypto/builtin/aes/Makefile.in
new file mode 100644
index 0000000..ed36f7e
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/Makefile.in
@@ -0,0 +1,61 @@
+thisconfigdir=../../../..
+myfulldir=lib/crypto/builtin/aes
+mydir=lib/crypto/builtin/aes
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../krb/dk
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..\..
+##DOS##PREFIXDIR=aes
+##DOS##OBJFILE=..\$(OUTPRE)aes.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+STLIBOBJS=\
+ aescrypt.o \
+ aestab.o \
+ aeskey.o \
+ aes_s2k.o
+
+OBJS=\
+ $(OUTPRE)aescrypt.$(OBJEXT) \
+ $(OUTPRE)aestab.$(OBJEXT) \
+ $(OUTPRE)aeskey.$(OBJEXT) \
+ $(OUTPRE)aes_s2k.$(OBJEXT)
+
+SRCS=\
+ $(srcdir)/aescrypt.c \
+ $(srcdir)/aestab.c \
+ $(srcdir)/aeskey.c \
+ $(srcdir)/aes_s2k.c
+
+GEN_OBJS=\
+ $(OUTPRE)aescrypt.$(OBJEXT) \
+ $(OUTPRE)aestab.$(OBJEXT) \
+ $(OUTPRE)aeskey.$(OBJEXT)
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs # aes-gen
+
+includes:: depend
+
+depend:: $(SRCS)
+
+aes-gen: aes-gen.o $(GEN_OBJS)
+ $(CC_LINK) -o aes-gen aes-gen.o $(GEN_OBJS)
+
+run-aes-gen: aes-gen
+ ./aes-gen > kresults.out
+
+check:: run-aes-gen
+
+
+clean-unix:: clean-libobjs
+
+clean::
+ -$(RM) aes-gen aes-gen.o kresults.out
+
+@libobj_frag@
+
diff --git a/src/lib/crypto/builtin/aes/aes-gen.c b/src/lib/crypto/builtin/aes/aes-gen.c
new file mode 100644
index 0000000..855e6a4
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aes-gen.c
@@ -0,0 +1,326 @@
+/*
+ * To be compiled against the AES code from:
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael/index.htm
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "aes.h"
+
+#define B 16U
+unsigned char key[16];
+unsigned char test_case_len[] = { B+1, 2*B-1, 2*B, 2*B+1, 3*B-1, 3*B, 4*B, };
+#define NTESTS (sizeof(test_case_len))
+struct {
+ unsigned char ivec[16];
+ unsigned char input[4*16];
+ unsigned char output[4*16];
+} test_case[NTESTS];
+aes_ctx ctx, dctx;
+
+static void init ()
+{
+ int i, j, r;
+
+ srand(42);
+ for (i = 0; i < 16; i++)
+ key[i] = 0xff & rand();
+ memset(test_case, 0, sizeof(test_case));
+ for (i = 0; i < NTESTS; i++)
+ for (j = 0; j < test_case_len[i]; j++) {
+ test_case[i].input[j] = 0xff & rand();
+ }
+
+ r = aes_enc_key (key, sizeof(key), &ctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ r = aes_dec_key (key, sizeof(key), &dctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+}
+
+static void hexdump(const unsigned char *ptr, size_t len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ printf ("%s%02X", (i % 16 == 0) ? "\n " : " ", ptr[i]);
+}
+
+static void fips_test ()
+{
+ static const unsigned char fipskey[16] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ };
+ static const unsigned char input[16] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ };
+ static const unsigned char expected[16] = {
+ 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+ 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a,
+ };
+ unsigned char output[16];
+ unsigned char tmp[16];
+ aes_ctx fipsctx;
+ int r;
+
+ printf ("FIPS test:\nkey:");
+ hexdump (fipskey, 16);
+ printf ("\ninput:");
+ hexdump (input, 16);
+ r = aes_enc_key (fipskey, sizeof(fipskey), &fipsctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ r = aes_enc_blk (input, output, &fipsctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ printf ("\noutput:");
+ hexdump (output, 16);
+ printf ("\n");
+ if (memcmp(expected, output, 16))
+ fprintf(stderr, "wrong results!!!\n"), exit (1);
+ r = aes_dec_key (fipskey, sizeof(fipskey), &fipsctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ r = aes_dec_blk (output, tmp, &fipsctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ if (memcmp(input, tmp, 16))
+ fprintf(stderr, "decryption failed!!\n"), exit(1);
+ printf ("ok.\n\n");
+}
+
+static void
+xor (unsigned char *out, const unsigned char *a, const unsigned char *b)
+{
+ int i;
+ for (i = 0; i < B; i++)
+ out[i] = a[i] ^ b[i];
+}
+
+static void
+ecb_enc (unsigned char *out, unsigned char *in, unsigned int len)
+{
+ int i, r;
+ for (i = 0; i < len; i += 16) {
+ r = aes_enc_blk (in + i, out + i, &ctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ }
+ if (i != len) abort ();
+}
+
+static void
+ecb_dec (unsigned char *out, unsigned char *in, unsigned int len)
+{
+ int i, r;
+ for (i = 0; i < len; i += 16) {
+ r = aes_dec_blk (in + i, out + i, &dctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ }
+ if (i != len) abort ();
+}
+
+#define D(X) (printf("%s %d: %s=",__FUNCTION__,__LINE__, #X),hexdump(X,B),printf("\n"))
+
+#undef D
+#define D(X)
+
+static void
+cbc_enc (unsigned char *out, unsigned char *in, unsigned char *iv,
+ unsigned int len)
+{
+ int i, r;
+ unsigned char tmp[B];
+ D(iv);
+ memcpy (tmp, iv, B);
+ for (i = 0; i < len; i += B) {
+ D(in+i);
+ xor (tmp, tmp, in + i);
+ D(tmp);
+ r = aes_enc_blk (tmp, out + i, &ctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ memcpy (tmp, out + i, B);
+ D(out+i);
+ }
+ if (i != len) abort ();
+}
+
+static void
+cbc_dec (unsigned char *out, unsigned char *in, unsigned char *iv,
+ unsigned int len)
+{
+ int i, r;
+ unsigned char tmp[B];
+ memcpy (tmp, iv, B);
+ for (i = 0; i < len; i += B) {
+ r = aes_dec_blk (in + i, tmp, &dctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ xor (tmp, tmp, iv);
+ iv = in + i;
+ memcpy (out + i, tmp, B);
+ }
+ if (i != len) abort ();
+}
+
+static void
+cts_enc (unsigned char *out, unsigned char *in, unsigned char *iv,
+ unsigned int len)
+{
+ int r;
+ unsigned int len2;
+ unsigned char pn1[B], pn[B], cn[B], cn1[B];
+
+ if (len < B + 1) abort ();
+ len2 = (len - B - 1) & ~(B-1);
+ cbc_enc (out, in, iv, len2);
+ out += len2;
+ in += len2;
+ len -= len2;
+ if (len2)
+ iv = out - B;
+ if (len <= B || len > 2 * B)
+ abort ();
+ printf ("(did CBC mode for %d)\n", len2);
+
+ D(in);
+ xor (pn1, in, iv);
+ D(pn1);
+ r = aes_enc_blk (pn1, cn, &ctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ D(cn);
+ memset (pn, 0, sizeof(pn));
+ memcpy (pn, in+B, len-B);
+ D(pn);
+ xor (pn, pn, cn);
+ D(pn);
+ r = aes_enc_blk (pn, cn1, &ctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ D(cn1);
+ memcpy(out, cn1, B);
+ memcpy(out+B, cn, len-B);
+}
+
+static void
+cts_dec (unsigned char *out, unsigned char *in, unsigned char *iv,
+ unsigned int len)
+{
+ int r;
+ unsigned int len2;
+ unsigned char pn1[B], pn[B], cn[B], cn1[B];
+
+ if (len < B + 1) abort ();
+ len2 = (len - B - 1) & ~(B-1);
+ cbc_dec (out, in, iv, len2);
+ out += len2;
+ in += len2;
+ len -= len2;
+ if (len2)
+ iv = in - B;
+ if (len <= B || len > 2 * B)
+ abort ();
+
+ memcpy (cn1, in, B);
+ r = aes_dec_blk (cn1, pn, &dctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ memset (cn, 0, sizeof(cn));
+ memcpy (cn, in+B, len-B);
+ xor (pn, pn, cn);
+ memcpy (cn+len-B, pn+len-B, 2*B-len);
+ r = aes_dec_blk (cn, pn1, &dctx);
+ if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1);
+ xor (pn1, pn1, iv);
+ memcpy(out, pn1, B);
+ memcpy(out+B, pn, len-B);
+}
+
+static void ecb_test ()
+{
+ int testno;
+ unsigned char tmp[4*B];
+
+ printf ("ECB tests:\n");
+ printf ("key:");
+ hexdump (key, sizeof(key));
+ for (testno = 0; testno < NTESTS; testno++) {
+ unsigned len = (test_case_len[testno] + 15) & ~15;
+ printf ("\ntest %d - %d bytes\n", testno, len);
+ printf ("input:");
+ hexdump (test_case[testno].input, len);
+ printf ("\n");
+ ecb_enc (test_case[testno].output, test_case[testno].input, len);
+ printf ("output:");
+ hexdump (test_case[testno].output, len);
+ printf ("\n");
+ ecb_dec (tmp, test_case[testno].output, len);
+ if (memcmp (tmp, test_case[testno].input, len)) {
+ printf ("ecb decrypt failed!!");
+ hexdump (tmp, len);
+ printf ("\n");
+ exit (1);
+ }
+ }
+ printf ("\n");
+}
+
+unsigned char ivec[16] = { 0 };
+
+static void cbc_test ()
+{
+ int testno;
+ unsigned char tmp[4*B];
+
+ printf ("CBC tests:\n");
+ printf ("initial vector:");
+ hexdump (ivec, sizeof(ivec));
+ for (testno = 0; testno < NTESTS; testno++) {
+ unsigned len = (test_case_len[testno] + 15) & ~15;
+ printf ("\ntest %d - %d bytes\n", testno, len);
+ printf ("input:");
+ hexdump (test_case[testno].input, len);
+ printf ("\n");
+ cbc_enc (test_case[testno].output, test_case[testno].input, ivec, len);
+ printf ("output:");
+ hexdump (test_case[testno].output, len);
+ printf ("\n");
+ cbc_dec (tmp, test_case[testno].output, ivec, len);
+ if (memcmp (tmp, test_case[testno].input, len)) {
+ printf("cbc decrypt failed!!");
+ hexdump (tmp, len);
+ printf ("\n");
+ exit(1);
+ }
+ }
+ printf ("\n");
+}
+
+static void cts_test ()
+{
+ int testno;
+ unsigned char tmp[4*B];
+
+ printf ("CTS tests:\n");
+ printf ("initial vector:");
+ hexdump (ivec, sizeof(ivec));
+ for (testno = 0; testno < NTESTS; testno++) {
+ unsigned int len = test_case_len[testno];
+ printf ("\ntest %d - %d bytes\n", testno, len);
+ printf ("input:");
+ hexdump (test_case[testno].input, len);
+ printf ("\n");
+ cts_enc (test_case[testno].output, test_case[testno].input, ivec, len);
+ printf ("output:");
+ hexdump (test_case[testno].output, len);
+ printf ("\n");
+ cts_dec (tmp, test_case[testno].output, ivec, len);
+ if (memcmp (tmp, test_case[testno].input, len))
+ fprintf (stderr, "cts decrypt failed!!\n"), exit(1);
+ }
+ printf ("\n");
+}
+
+int main ()
+{
+ init ();
+ fips_test ();
+
+ ecb_test();
+ cbc_test();
+ cts_test();
+
+ return 0;
+}
diff --git a/src/lib/crypto/builtin/aes/aes.h b/src/lib/crypto/builtin/aes/aes.h
new file mode 100644
index 0000000..ac1c1b8
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aes.h
@@ -0,0 +1,97 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+ 1. distributions of this source code include the above copyright
+ notice, this list of conditions and the following disclaimer;
+
+ 2. distributions in binary form include the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other associated materials;
+
+ 3. the copyright holder's name is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the definitions required to use AES (Rijndael) in C.
+*/
+
+#ifndef _AES_H
+#define _AES_H
+
+#include "uitypes.h"
+
+/* BLOCK_SIZE is in BYTES: 16, 24, 32 or undefined for aes.c and 16, 20,
+ 24, 28, 32 or undefined for aespp.c. When left undefined a slower
+ version that provides variable block length is compiled.
+*/
+
+#define BLOCK_SIZE 16
+
+/* key schedule length (in 32-bit words) */
+
+#if !defined(BLOCK_SIZE)
+#define KS_LENGTH 128
+#else
+#define KS_LENGTH 4 * BLOCK_SIZE
+#endif
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+typedef uint16_t aes_fret; /* type for function return value */
+#define aes_bad 0 /* bad function return value */
+#define aes_good 1 /* good function return value */
+#ifndef AES_DLL /* implement normal or DLL functions */
+#define aes_rval aes_fret
+#else
+#define aes_rval aes_fret __declspec(dllexport) _stdcall
+#endif
+
+typedef struct /* the AES context for encryption */
+{ uint32_t k_sch[KS_LENGTH]; /* the encryption key schedule */
+ uint32_t n_rnd; /* the number of cipher rounds */
+ uint32_t n_blk; /* the number of bytes in the state */
+} aes_ctx;
+
+/* for Kerberos 5 tree -- hide names! */
+#define aes_blk_len krb5int_aes_blk_len
+#define aes_enc_key krb5int_aes_enc_key
+#define aes_enc_blk krb5int_aes_enc_blk
+#define aes_dec_key krb5int_aes_dec_key
+#define aes_dec_blk krb5int_aes_dec_blk
+#define fl_tab krb5int_fl_tab
+#define ft_tab krb5int_ft_tab
+#define il_tab krb5int_il_tab
+#define im_tab krb5int_im_tab
+#define it_tab krb5int_it_tab
+#define rcon_tab krb5int_rcon_tab
+
+aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]);
+
+aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);
+aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+
+aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);
+aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/src/lib/crypto/builtin/aes/aes.txt b/src/lib/crypto/builtin/aes/aes.txt
new file mode 100644
index 0000000..b644b5e
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aes.txt
@@ -0,0 +1,70 @@
+
+An AES (Rijndael) Implementation in C/C++ (as specified in FIPS-197)
+--------------------------------------------------------------------
+
+The source code files are as follows:
+
+1. aes.h: the header file required to use AES in C
+2. aescpp.h the header file required to use AES in C++
+3. aescrypt.c the main C source code file for encryption and decryption
+4. aeskey.c the main C source code file for the key schedule
+5. aestab.c the main file for the AES tables
+6. aesopt.h the file for common code and for setting build options
+7. aescrypt.asm a faster alternative to 3 above in assembler (using NASM)
+8. uitypes.h a file for defining fixed length unsigned integer types
+9. aescrypp.c an alternative to 3 for all Rijndael block and key sizes
+10.aeskeypp.c an alternative to 4 for all Rijndael block and key sizes
+11.aesxam.c an example of AES use
+
+Source files 9 and 10 are much slower than 4 and 5 for normal use and
+should not be used unless support for 20 and 28 byte blocks and keys
+is necessary. Files 4 and 5 provide support for block and key sizes
+of 16, 24 and 32 bytes (fixed or variable) but the assemler code in
+file 7 only supports the 16 byte AES block length. It does, however,
+offer the three key sizes when used with file 4. The use of files 4
+and 5 (or 9 and 10) with variable block size should be avoided since
+the code is much faster when the block size is fixed.
+
+The VC++ AES Development Project
+--------------------------------
+
+The VC++ SOlution contains the following sub-projects
+
+1. aes_asm this project tests the assembler code implementation
+2. aes_dll this project builds the DLL version
+3. aes_gav this project re-creates the test vector files and
+ optionally checks them against a reference set
+4. aes_rav this project checks the values produced by the code
+ against the values in the test vector files
+5. aes_tmr this project measures the speed of the code
+6. aes_tst this project is set up to test the extended version
+ of Rijndael with block and key sizes of 16, 20, 24,
+ 28 and 32 bytes
+7. aes_xam this project builds the example of AES use in a
+ simple file encryption program
+
+Note that the paths for the various directories have to be set up in
+aestst.h
+
+The AES and Rijndael Test Vector Files
+--------------------------------------
+
+These files fall in the following groups (where <nn> is a two digit
+number):
+
+1. ecbvk<nn>.txt ECB vectors with variable key
+2. ecbvt<nn>.txt ECB vectors with variable text
+3. ecbnk<nn>.txt new ECB vectors with variable key
+4. ecbnt<nn>.txt new ECB vectors with variable text
+5. ecbme<nn>.txt ECB monte carlo encryption test vectors
+6. ecbmd<nn>.txt ECB monte carlo decryption test vectors
+7. cbcme<nn>.txt CBC monte carlo encryption test vectors
+8. cbcmd<nn>.txt CBC monte carlo decryption test vectors
+
+The first digit of the numeric suffix on the filename gives the
+block size in 32bit units and the second numeric digit gives the
+key size. For example, the file ecbvk44.txt provides the test
+vectors for ECB encryption with a 128 bit block size and a 128
+bit key size.
+
+ Brian Gladman <brg@gladman.uk.net> \ No newline at end of file
diff --git a/src/lib/crypto/builtin/aes/aes_s2k.c b/src/lib/crypto/builtin/aes/aes_s2k.c
new file mode 100644
index 0000000..36045ed
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aes_s2k.c
@@ -0,0 +1,90 @@
+/*
+ * lib/crypto/aes/aes_s2k.c
+ *
+ * Copyright 2003 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ * krb5int_aes_string_to_key
+ */
+
+#include "k5-int.h"
+#include "dk.h"
+#include "aes_s2k.h"
+
+#define DEFAULT_ITERATION_COUNT 4096 /* was 0xb000L in earlier drafts */
+#define MAX_ITERATION_COUNT 0x1000000L
+
+krb5_error_code
+krb5int_aes_string_to_key(const struct krb5_enc_provider *enc,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key)
+{
+ unsigned long iter_count;
+ krb5_data out;
+ static const krb5_data usage = { KV5M_DATA, 8, "kerberos" };
+ krb5_error_code err;
+
+ if (params) {
+ unsigned char *p = (unsigned char *) params->data;
+ if (params->length != 4)
+ return KRB5_ERR_BAD_S2K_PARAMS;
+ /* The first two need casts in case 'int' is 16 bits. */
+ iter_count = load_32_be(p);
+ if (iter_count == 0) {
+ iter_count = (1UL << 16) << 16;
+ if (((iter_count >> 16) >> 16) != 1)
+ return KRB5_ERR_BAD_S2K_PARAMS;
+ }
+ } else
+ iter_count = DEFAULT_ITERATION_COUNT;
+
+ /* This is not a protocol specification constraint; this is an
+ implementation limit, which should eventually be controlled by
+ a config file. */
+ if (iter_count >= MAX_ITERATION_COUNT)
+ return KRB5_ERR_BAD_S2K_PARAMS;
+
+ /*
+ * Dense key space, no parity bits or anything, so take a shortcut
+ * and use the key contents buffer for the generated bytes.
+ */
+ out.data = (char *) key->contents;
+ out.length = key->length;
+ if (out.length != 16 && out.length != 32)
+ return KRB5_CRYPTO_INTERNAL;
+
+ err = krb5int_pbkdf2_hmac_sha1 (&out, iter_count, string, salt);
+ if (err) {
+ memset(out.data, 0, out.length);
+ return err;
+ }
+
+ err = krb5_derive_key (enc, key, key, &usage);
+ if (err) {
+ memset(out.data, 0, out.length);
+ return err;
+ }
+ return 0;
+}
diff --git a/src/lib/crypto/builtin/aes/aes_s2k.h b/src/lib/crypto/builtin/aes/aes_s2k.h
new file mode 100644
index 0000000..b6804a9
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aes_s2k.h
@@ -0,0 +1,4 @@
+extern krb5_error_code
+krb5int_aes_string_to_key (const struct krb5_enc_provider *,
+ const krb5_data *, const krb5_data *,
+ const krb5_data *, krb5_keyblock *key);
diff --git a/src/lib/crypto/builtin/aes/aescpp.h b/src/lib/crypto/builtin/aes/aescpp.h
new file mode 100644
index 0000000..e685485
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aescpp.h
@@ -0,0 +1,55 @@
+
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ TERMS
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted subject to the following conditions:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The copyright holder's name must not be used to endorse or promote
+ any products derived from this software without his specific prior
+ written permission.
+
+ This software is provided 'as is' with no express or implied warranties
+ of correctness or fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the definitions required to use AES (Rijndael) in C++.
+*/
+
+#ifndef _AESCPP_H
+#define _AESCPP_H
+
+#include "aes.h"
+
+class AESclass
+{ aes_ctx cx[1];
+public:
+#if defined(BLOCK_SIZE)
+ AESclass() { cx->n_blk = BLOCK_SIZE; cx->n_rnd = 0; }
+#else
+ AESclass(unsigned int blen = 16) { cx->n_blk = blen; cx->n_rnd = 0; }
+#endif
+ aes_rval blk_len(unsigned int blen) { return aes_blk_len(blen, cx); }
+ aes_rval enc_key(const unsigned char in_key[], unsigned int klen)
+ { return aes_enc_key(in_key, klen, cx); }
+ aes_rval dec_key(const unsigned char in_key[], unsigned int klen)
+ { return aes_dec_key(in_key, klen, cx); }
+ aes_rval enc_blk(const unsigned char in_blk[], unsigned char out_blk[])
+ { return aes_enc_blk(in_blk, out_blk, cx); }
+ aes_rval dec_blk(const unsigned char in_blk[], unsigned char out_blk[])
+ { return aes_dec_blk(in_blk, out_blk, cx); }
+};
+
+#endif
diff --git a/src/lib/crypto/builtin/aes/aescrypp.c b/src/lib/crypto/builtin/aes/aescrypp.c
new file mode 100644
index 0000000..87b6341
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aescrypp.c
@@ -0,0 +1,487 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+ 1. distributions of this source code include the above copyright
+ notice, this list of conditions and the following disclaimer;
+
+ 2. distributions in binary form include the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other associated materials;
+
+ 3. the copyright holder's name is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the code for implementing encryption and decryption
+ for AES (Rijndael) for block and key sizes of 16, 20, 24, 28 and 32 bytes.
+ It can optionally be replaced by code written in assembler using NASM.
+*/
+
+#include "aesopt.h"
+
+#define unused 77 /* Sunset Strip */
+
+#define si(y,x,k,c) s(y,c) = word_in(x + 4 * c) ^ k[c]
+#define so(y,x,c) word_out(y + 4 * c, s(x,c))
+
+#if BLOCK_SIZE == 16
+
+#if defined(ARRAYS)
+#define locals(y,x) x[4],y[4]
+#else
+#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
+ /*
+ the following defines prevent the compiler requiring the declaration
+ of generated but unused variables in the fwd_var and inv_var macros
+ */
+#define b04 unused
+#define b05 unused
+#define b06 unused
+#define b07 unused
+#define b14 unused
+#define b15 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
+ s(y,2) = s(x,2); s(y,3) = s(x,3);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
+
+#elif BLOCK_SIZE == 20
+
+#if defined(ARRAYS)
+#define locals(y,x) x[5],y[5]
+#else
+#define locals(y,x) x##0,x##1,x##2,x##3,x##4,y##0,y##1,y##2,y##3,y##4
+#define b05 unused
+#define b06 unused
+#define b07 unused
+#define b15 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
+ s(y,2) = s(x,2); s(y,3) = s(x,3); s(y,4) = s(x,4);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); si(y,x,k,4)
+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); so(y,x,4)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); rm(y,x,k,4)
+
+#elif BLOCK_SIZE == 24
+
+#if defined(ARRAYS)
+#define locals(y,x) x[6],y[6]
+#else
+#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5, \
+ y##0,y##1,y##2,y##3,y##4,y##5
+#define b06 unused
+#define b07 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
+ s(y,2) = s(x,2); s(y,3) = s(x,3); \
+ s(y,4) = s(x,4); s(y,5) = s(x,5);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \
+ si(y,x,k,3); si(y,x,k,4); si(y,x,k,5)
+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \
+ so(y,x,3); so(y,x,4); so(y,x,5)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \
+ rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5)
+
+#elif BLOCK_SIZE == 28
+
+#if defined(ARRAYS)
+#define locals(y,x) x[7],y[7]
+#else
+#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6 \
+ y##0,y##1,y##2,y##3,y##4,y##5,y##6
+#define b07 unused
+#define b17 unused
+#endif
+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
+ s(y,2) = s(x,2); s(y,3) = s(x,3); \
+ s(y,4) = s(x,4); s(y,5) = s(x,5);; s(y,6) = s(x,6);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \
+ si(y,x,k,3); si(y,x,k,4); si(y,x,k,5); si(y,x,k,6)
+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \
+ so(y,x,3); so(y,x,4); so(y,x,5); so(y,x,6)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \
+ rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6)
+#else
+
+#if defined(ARRAYS)
+#define locals(y,x) x[8],y[8]
+#else
+#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \
+ y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7
+#endif
+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
+ s(y,2) = s(x,2); s(y,3) = s(x,3); \
+ s(y,4) = s(x,4); s(y,5) = s(x,5); \
+ s(y,6) = s(x,6); s(y,7) = s(x,7);
+
+#if BLOCK_SIZE == 32
+
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \
+ si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7)
+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \
+ so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \
+ rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7)
+#else
+
+#define state_in(y,x,k) \
+switch(nc) \
+{ case 8: si(y,x,k,7); \
+ case 7: si(y,x,k,6); \
+ case 6: si(y,x,k,5); \
+ case 5: si(y,x,k,4); \
+ case 4: si(y,x,k,3); si(y,x,k,2); \
+ si(y,x,k,1); si(y,x,k,0); \
+}
+
+#define state_out(y,x) \
+switch(nc) \
+{ case 8: so(y,x,7); \
+ case 7: so(y,x,6); \
+ case 6: so(y,x,5); \
+ case 5: so(y,x,4); \
+ case 4: so(y,x,3); so(y,x,2); \
+ so(y,x,1); so(y,x,0); \
+}
+
+#if defined(FAST_VARIABLE)
+
+#define round(rm,y,x,k) \
+switch(nc) \
+{ case 8: rm(y,x,k,7); rm(y,x,k,6); \
+ rm(y,x,k,5); rm(y,x,k,4); \
+ rm(y,x,k,3); rm(y,x,k,2); \
+ rm(y,x,k,1); rm(y,x,k,0); \
+ break; \
+ case 7: rm(y,x,k,6); rm(y,x,k,5); \
+ rm(y,x,k,4); rm(y,x,k,3); \
+ rm(y,x,k,2); rm(y,x,k,1); \
+ rm(y,x,k,0); \
+ break; \
+ case 6: rm(y,x,k,5); rm(y,x,k,4); \
+ rm(y,x,k,3); rm(y,x,k,2); \
+ rm(y,x,k,1); rm(y,x,k,0); \
+ break; \
+ case 5: rm(y,x,k,4); rm(y,x,k,3); \
+ rm(y,x,k,2); rm(y,x,k,1); \
+ rm(y,x,k,0); \
+ break; \
+ case 4: rm(y,x,k,3); rm(y,x,k,2); \
+ rm(y,x,k,1); rm(y,x,k,0); \
+ break; \
+}
+#else
+
+#define round(rm,y,x,k) \
+switch(nc) \
+{ case 8: rm(y,x,k,7); \
+ case 7: rm(y,x,k,6); \
+ case 6: rm(y,x,k,5); \
+ case 5: rm(y,x,k,4); \
+ case 4: rm(y,x,k,3); rm(y,x,k,2); \
+ rm(y,x,k,1); rm(y,x,k,0); \
+}
+
+#endif
+
+#endif
+#endif
+
+#if defined(ENCRYPTION)
+
+/* I am grateful to Frank Yellin for the following construction
+ (and that for decryption) which, given the column (c) of the
+ output state variable, gives the input state variables which
+ are needed for each row (r) of the state.
+
+ For the fixed block size options, compilers should reduce these
+ two expressions to fixed variable references. But for variable
+ block size code conditional clauses will sometimes be returned.
+
+ y = output word, x = input word, r = row, c = column for r = 0,
+ 1, 2 and 3 = column accessed for row r.
+*/
+
+#define fwd_var(x,r,c) \
+ ( r==0 ? \
+ ( c==0 ? s(x,0) \
+ : c==1 ? s(x,1) \
+ : c==2 ? s(x,2) \
+ : c==3 ? s(x,3) \
+ : c==4 ? s(x,4) \
+ : c==5 ? s(x,5) \
+ : c==6 ? s(x,6) \
+ : s(x,7)) \
+ : r==1 ? \
+ ( c==0 ? s(x,1) \
+ : c==1 ? s(x,2) \
+ : c==2 ? s(x,3) \
+ : c==3 ? nc==4 ? s(x,0) : s(x,4) \
+ : c==4 ? nc==5 ? s(x,0) : s(x,5) \
+ : c==5 ? nc==6 ? s(x,0) : s(x,6) \
+ : c==6 ? nc==7 ? s(x,0) : s(x,7) \
+ : s(x,0)) \
+ : r==2 ? \
+ ( c==0 ? nc==8 ? s(x,3) : s(x,2) \
+ : c==1 ? nc==8 ? s(x,4) : s(x,3) \
+ : c==2 ? nc==8 ? s(x,5) : nc==4 ? s(x,0) : s(x,4) \
+ : c==3 ? nc==8 ? s(x,6) : nc==5 ? s(x,0) : nc==4 ? s(x,1) : s(x,5) \
+ : c==4 ? nc==8 ? s(x,7) : nc==7 ? s(x,6) : nc==6 ? s(x,0) : s(x,1) \
+ : c==5 ? nc==6 ? s(x,1) : s(x,0) \
+ : c==6 ? s(x,1) \
+ : s(x,2)) \
+ : \
+ ( c==0 ? nc>6 ? s(x,4) : s(x,3) \
+ : c==1 ? nc>6 ? s(x,5) : nc==4 ? s(x,0) : s(x,4) \
+ : c==2 ? nc>6 ? s(x,6) : nc==6 ? s(x,5) : nc==5 ? s(x,0) : s(x,1) \
+ : c==3 ? nc==8 ? s(x,7) : nc==5 ? s(x,1) : nc==4 ? s(x,2) : s(x,0) \
+ : c==4 ? nc==8 ? s(x,0) : nc==5 ? s(x,2) : s(x,1) \
+ : c==5 ? nc==8 ? s(x,1) : s(x,2) \
+ : c==6 ? nc==8 ? s(x,2) : s(x,3) \
+ : s(x,3)))
+
+#if defined(FT4_SET)
+#undef dec_fmvars
+#define dec_fmvars
+#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c)
+#elif defined(FT1_SET)
+#undef dec_fmvars
+#define dec_fmvars
+#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c)
+#else
+#define fwd_rnd(y,x,k,c) s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c]
+#endif
+
+#if defined(FL4_SET)
+#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c)
+#elif defined(FL1_SET)
+#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c)
+#else
+#define fwd_lrnd(y,x,k,c) s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c]
+#endif
+
+aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])
+{ uint32_t locals(b0, b1);
+ const uint32_t *kp = cx->k_sch;
+ dec_fmvars /* declare variables for fwd_mcol() if needed */
+
+ if(!(cx->n_blk & 1)) return aes_bad;
+
+#if (ENC_UNROLL == FULL)
+
+ state_in((cx->n_rnd & 1 ? b1 : b0), in_blk, kp);
+ kp += (cx->n_rnd - 9) * nc;
+
+ switch(cx->n_rnd)
+ {
+ case 14: round(fwd_rnd, b1, b0, kp - 4 * nc);
+ case 13: round(fwd_rnd, b0, b1, kp - 3 * nc);
+ case 12: round(fwd_rnd, b1, b0, kp - 2 * nc);
+ case 11: round(fwd_rnd, b0, b1, kp - nc);
+ case 10: round(fwd_rnd, b1, b0, kp );
+ round(fwd_rnd, b0, b1, kp + nc);
+ round(fwd_rnd, b1, b0, kp + 2 * nc);
+ round(fwd_rnd, b0, b1, kp + 3 * nc);
+ round(fwd_rnd, b1, b0, kp + 4 * nc);
+ round(fwd_rnd, b0, b1, kp + 5 * nc);
+ round(fwd_rnd, b1, b0, kp + 6 * nc);
+ round(fwd_rnd, b0, b1, kp + 7 * nc);
+ round(fwd_rnd, b1, b0, kp + 8 * nc);
+ round(fwd_lrnd, b0, b1, kp + 9 * nc);
+ }
+#else
+ { uint32_t rnd;
+
+ state_in(b0, in_blk, kp);
+
+#if (ENC_UNROLL == PARTIAL)
+
+ for(rnd = 0; rnd < (cx->n_rnd - 1) >> 1; ++rnd)
+ {
+ kp += nc;
+ round(fwd_rnd, b1, b0, kp);
+ kp += nc;
+ round(fwd_rnd, b0, b1, kp);
+ }
+
+ if(cx->n_rnd & 1)
+ {
+ l_copy(b1, b0);
+ }
+ else
+ {
+ kp += nc;
+ round(fwd_rnd, b1, b0, kp);
+ }
+#else
+ for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd)
+ {
+ kp += nc;
+ round(fwd_rnd, b1, b0, kp);
+ l_copy(b0, b1);
+ }
+#endif
+ kp += nc;
+ round(fwd_lrnd, b0, b1, kp);
+ }
+#endif
+
+ state_out(out_blk, b0);
+ return aes_good;
+}
+
+#endif
+
+#if defined(DECRYPTION)
+
+#define inv_var(x,r,c) \
+ ( r==0 ? \
+ ( c==0 ? s(x,0) \
+ : c==1 ? s(x,1) \
+ : c==2 ? s(x,2) \
+ : c==3 ? s(x,3) \
+ : c==4 ? s(x,4) \
+ : c==5 ? s(x,5) \
+ : c==6 ? s(x,6) \
+ : s(x,7)) \
+ : r==1 ? \
+ ( c==0 ? nc==8 ? s(x,7) : nc==7 ? s(x,6) : nc==6 ? s(x,5) : nc==5 ? s(x,4) : s(x,3) \
+ : c==1 ? s(x,0) \
+ : c==2 ? s(x,1) \
+ : c==3 ? s(x,2) \
+ : c==4 ? s(x,3) \
+ : c==5 ? s(x,4) \
+ : c==6 ? s(x,5) \
+ : s(x,6)) \
+ : r==2 ? \
+ ( c==0 ? nc>6 ? s(x,5) : nc==6 ? s(x,4) : nc==5 ? s(x,3) : s(x,2) \
+ : c==1 ? nc>6 ? s(x,6) : nc==6 ? s(x,5) : nc==5 ? s(x,4) : s(x,3) \
+ : c==2 ? nc==8 ? s(x,7) : s(x,0) \
+ : c==3 ? nc==8 ? s(x,0) : s(x,1) \
+ : c==4 ? nc==8 ? s(x,1) : s(x,2) \
+ : c==5 ? nc==8 ? s(x,2) : s(x,3) \
+ : c==6 ? nc==8 ? s(x,3) : s(x,4) \
+ : s(x,4)) \
+ : \
+ ( c==0 ? nc==8 ? s(x,4) : nc==5 ? s(x,2) : nc==4 ? s(x,1) : s(x,3) \
+ : c==1 ? nc==8 ? s(x,5) : nc==5 ? s(x,3) : nc==4 ? s(x,2) : s(x,4) \
+ : c==2 ? nc==8 ? s(x,6) : nc==5 ? s(x,4) : nc==4 ? s(x,3) : s(x,5) \
+ : c==3 ? nc==8 ? s(x,7) : nc==7 ? s(x,6) : s(x,0) \
+ : c==4 ? nc>6 ? s(x,0) : s(x,1) \
+ : c==5 ? nc==6 ? s(x,2) : s(x,1) \
+ : c==6 ? s(x,2) \
+ : s(x,3)))
+
+#if defined(IT4_SET)
+#undef dec_imvars
+#define dec_imvars
+#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c)
+#elif defined(IT1_SET)
+#undef dec_imvars
+#define dec_imvars
+#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c)
+#else
+#define inv_rnd(y,x,k,c) s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c])
+#endif
+
+#if defined(IL4_SET)
+#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c)
+#elif defined(IL1_SET)
+#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c)
+#else
+#define inv_lrnd(y,x,k,c) s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]
+#endif
+
+aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])
+{ uint32_t locals(b0, b1);
+ const uint32_t *kp = cx->k_sch + nc * cx->n_rnd;
+ dec_imvars /* declare variables for inv_mcol() if needed */
+
+ if(!(cx->n_blk & 2)) return aes_bad;
+
+#if (DEC_UNROLL == FULL)
+
+ state_in((cx->n_rnd & 1 ? b1 : b0), in_blk, kp);
+ kp = cx->k_sch + 9 * nc;
+
+ switch(cx->n_rnd)
+ {
+ case 14: round(inv_rnd, b1, b0, kp + 4 * nc);
+ case 13: round(inv_rnd, b0, b1, kp + 3 * nc);
+ case 12: round(inv_rnd, b1, b0, kp + 2 * nc);
+ case 11: round(inv_rnd, b0, b1, kp + nc);
+ case 10: round(inv_rnd, b1, b0, kp );
+ round(inv_rnd, b0, b1, kp - nc);
+ round(inv_rnd, b1, b0, kp - 2 * nc);
+ round(inv_rnd, b0, b1, kp - 3 * nc);
+ round(inv_rnd, b1, b0, kp - 4 * nc);
+ round(inv_rnd, b0, b1, kp - 5 * nc);
+ round(inv_rnd, b1, b0, kp - 6 * nc);
+ round(inv_rnd, b0, b1, kp - 7 * nc);
+ round(inv_rnd, b1, b0, kp - 8 * nc);
+ round(inv_lrnd, b0, b1, kp - 9 * nc);
+ }
+#else
+ { uint32_t rnd;
+
+ state_in(b0, in_blk, kp);
+
+#if (DEC_UNROLL == PARTIAL)
+
+ for(rnd = 0; rnd < (cx->n_rnd - 1) >> 1; ++rnd)
+ {
+ kp -= nc;
+ round(inv_rnd, b1, b0, kp);
+ kp -= nc;
+ round(inv_rnd, b0, b1, kp);
+ }
+
+ if(cx->n_rnd & 1)
+ {
+ l_copy(b1, b0);
+ }
+ else
+ {
+ kp -= nc;
+ round(inv_rnd, b1, b0, kp);
+ }
+#else
+ for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd)
+ {
+ kp -= nc;
+ round(inv_rnd, b1, b0, kp);
+ l_copy(b0, b1);
+ }
+#endif
+ kp -= nc;
+ round(inv_lrnd, b0, b1, kp);
+ }
+#endif
+
+ state_out(out_blk, b0);
+ return aes_good;
+}
+
+#endif
diff --git a/src/lib/crypto/builtin/aes/aescrypt.asm b/src/lib/crypto/builtin/aes/aescrypt.asm
new file mode 100644
index 0000000..35a6818
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aescrypt.asm
@@ -0,0 +1,402 @@
+
+; -------------------------------------------------------------------------
+; Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+; All rights reserved.
+;
+; LICENSE TERMS
+;
+; The free distribution and use of this software in both source and binary
+; form is allowed (with or without changes) provided that:
+;
+; 1. distributions of this source code include the above copyright
+; notice, this list of conditions and the following disclaimer;
+;
+; 2. distributions in binary form include the above copyright
+; notice, this list of conditions and the following disclaimer
+; in the documentation and/or other associated materials;
+;
+; 3. the copyright holder's name is not used to endorse products
+; built using this software without specific written permission.
+;
+; DISCLAIMER
+;
+; This software is provided 'as is' with no explcit or implied warranties
+; in respect of any properties, including, but not limited to, correctness
+; and fitness for purpose.
+; -------------------------------------------------------------------------
+; Issue Date: 15/01/2002
+
+; An AES (Rijndael) implementation for the Pentium MMX family using the NASM
+; assembler <http://www.web-sites.co.uk/nasm/>. This version only implements
+; the standard AES block length (128 bits, 16 bytes) with the same interface
+; as that used in my C/C++ implementation. This code does not preserve the
+; eax, ecx or edx registers or the artihmetic status flags. However, the ebx,
+; esi, edi, and ebp registers are preserved across calls. Only encryption
+; and decryption are implemented here, the key schedule code being that from
+; compiling aes.c with USE_ASM defined. This code uses VC++ register saving
+; conentions; if it is used with another compiler, its conventions for using
+; and saving registers will need to be checked.
+
+ section .text use32
+
+; aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+; aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+
+ global _aes_enc_blk
+ global _aes_dec_blk
+
+ extern _ft_tab
+ extern _fl_tab
+ extern _it_tab
+ extern _il_tab
+
+;%define USE_MMX ; include this to use MMX registers for temporary storage
+;%define USE_EMMS ; include this if you make use of floating point operations
+
+%ifdef USE_MMX
+%ifdef USE_EMMS
+%define EMMS_ON
+%endif
+%endif
+
+tlen: equ 1024 ; length of each of 4 'xor' arrays (256 32-bit words)
+
+; offsets to parameters with one register pushed onto stack
+
+in_blk: equ 8 ; input byte array address parameter
+out_blk:equ 12 ; output byte array address parameter
+ctx: equ 16 ; AES context structure
+
+; offsets in context structure
+
+ksch: equ 0 ; encryption key schedule base address
+nrnd: equ 256 ; number of rounds
+nblk: equ 260 ; number of rounds
+
+; register mapping for encrypt and decrypt subroutines
+
+%define r0 eax
+%define r1 ebx
+%define r2 ecx
+%define r3 edx
+%define r4 esi
+%define r5 edi
+%define r6 ebp
+
+%define eaxl al
+%define eaxh ah
+%define ebxl bl
+%define ebxh bh
+%define ecxl cl
+%define ecxh ch
+%define edxl dl
+%define edxh dh
+
+; This macro takes a 32-bit word representing a column and uses
+; each of its four bytes to index into four tables of 256 32-bit
+; words to obtain values that are then xored into the appropriate
+; output registers r0, r1, r4 or r5.
+
+; Parameters:
+; %1 out_state[0]
+; %2 out_state[1]
+; %3 out_state[2]
+; %4 out_state[3]
+; %5 table base address
+; %6 input register for the round (destroyed)
+; %7 scratch register for the round
+
+%macro do_col 7
+
+ movzx %7,%6l
+ xor %1,[4*%7+%5]
+ movzx %7,%6h
+ shr %6,16
+ xor %2,[4*%7+%5+tlen]
+ movzx %7,%6l
+ movzx %6,%6h
+ xor %3,[4*%7+%5+2*tlen]
+ xor %4,[4*%6+%5+3*tlen]
+
+%endmacro
+
+; initialise output registers from the key schedule
+
+%macro do_fcol 8
+
+ mov %1,[%8]
+ movzx %7,%6l
+ mov %2,[%8+12]
+ xor %1,[4*%7+%5]
+ mov %4,[%8+ 4]
+ movzx %7,%6h
+ shr %6,16
+ xor %2,[4*%7+%5+tlen]
+ movzx %7,%6l
+ movzx %6,%6h
+ xor %4,[4*%6+%5+3*tlen]
+ mov %6,%3
+ mov %3,[%8+ 8]
+ xor %3,[4*%7+%5+2*tlen]
+
+%endmacro
+
+; initialise output registers from the key schedule
+
+%macro do_icol 8
+
+ mov %1,[%8]
+ movzx %7,%6l
+ mov %2,[%8+ 4]
+ xor %1,[4*%7+%5]
+ mov %4,[%8+12]
+ movzx %7,%6h
+ shr %6,16
+ xor %2,[4*%7+%5+tlen]
+ movzx %7,%6l
+ movzx %6,%6h
+ xor %4,[4*%6+%5+3*tlen]
+ mov %6,%3
+ mov %3,[%8+ 8]
+ xor %3,[4*%7+%5+2*tlen]
+
+%endmacro
+
+; These macros implement either MMX or stack based local variables
+
+%ifdef USE_MMX
+
+%macro save 2
+ movd mm%1,%2
+%endmacro
+
+%macro restore 2
+ movd %1,mm%2
+%endmacro
+
+%else
+
+%macro save 2
+ mov [esp+4*%1],%2
+%endmacro
+
+%macro restore 2
+ mov %1,[esp+4*%2]
+%endmacro
+
+%endif
+
+; This macro performs a forward encryption cycle. It is entered with
+; the first previous round column values in r0, r1, r4 and r5 and
+; exits with the final values in the same registers, using the MMX
+; registers mm0-mm1 for temporary storage
+
+%macro fwd_rnd 1-2 _ft_tab
+
+; mov current column values into the MMX registers
+
+ mov r2,r0
+ save 0,r1
+ save 1,r5
+
+; compute new column values
+
+ do_fcol r0,r5,r4,r1, %2, r2,r3, %1
+ do_col r4,r1,r0,r5, %2, r2,r3
+ restore r2,0
+ do_col r1,r0,r5,r4, %2, r2,r3
+ restore r2,1
+ do_col r5,r4,r1,r0, %2, r2,r3
+
+%endmacro
+
+; This macro performs an inverse encryption cycle. It is entered with
+; the first previous round column values in r0, r1, r4 and r5 and
+; exits with the final values in the same registers, using the MMX
+; registers mm0-mm1 for temporary storage
+
+%macro inv_rnd 1-2 _it_tab
+
+; mov current column values into the MMX registers
+
+ mov r2,r0
+ save 0,r1
+ save 1,r5
+
+; compute new column values
+
+ do_icol r0,r1,r4,r5, %2, r2,r3, %1
+ do_col r4,r5,r0,r1, %2, r2,r3
+ restore r2,0
+ do_col r1,r4,r5,r0, %2, r2,r3
+ restore r2,1
+ do_col r5,r0,r1,r4, %2, r2,r3
+
+%endmacro
+
+; AES (Rijndael) Encryption Subroutine
+
+_aes_enc_blk:
+ push ebp
+ mov ebp,[esp+ctx] ; pointer to context
+ xor eax,eax
+ test [ebp+nblk],byte 1
+ je .0
+ cmp eax,[ebp+nrnd] ; encryption/decryption flags
+ jne short .1
+.0: pop ebp
+ ret
+
+; CAUTION: the order and the values used in these assigns
+; rely on the register mappings
+
+.1: push ebx
+ mov r2,[esp+in_blk+4]
+ push esi
+ mov r3,[ebp+nrnd] ; number of rounds
+ push edi
+ lea r6,[ebp+ksch] ; key pointer
+
+; input four columns and xor in first round key
+
+ mov r0,[r2]
+ mov r1,[r2+4]
+ mov r4,[r2+8]
+ mov r5,[r2+12]
+ xor r0,[r6]
+ xor r1,[r6+4]
+ xor r4,[r6+8]
+ xor r5,[r6+12]
+
+%ifndef USE_MMX
+ sub esp,8 ; space for register saves on stack
+%endif
+ add r6,16 ; increment to next round key
+ sub r3,10
+ je .4 ; 10 rounds for 128-bit key
+ add r6,32
+ sub r3,2
+ je .3 ; 12 rounds for 128-bit key
+ add r6,32
+
+.2: fwd_rnd r6-64 ; 14 rounds for 128-bit key
+ fwd_rnd r6-48
+.3: fwd_rnd r6-32 ; 12 rounds for 128-bit key
+ fwd_rnd r6-16
+.4: fwd_rnd r6 ; 10 rounds for 128-bit key
+ fwd_rnd r6+ 16
+ fwd_rnd r6+ 32
+ fwd_rnd r6+ 48
+ fwd_rnd r6+ 64
+ fwd_rnd r6+ 80
+ fwd_rnd r6+ 96
+ fwd_rnd r6+112
+ fwd_rnd r6+128
+ fwd_rnd r6+144,_fl_tab ; last round uses a different table
+
+; move final values to the output array. CAUTION: the
+; order of these assigns rely on the register mappings
+
+%ifndef USE_MMX
+ add esp,8
+%endif
+ mov r6,[esp+out_blk+12]
+ mov [r6+12],r5
+ pop edi
+ mov [r6+8],r4
+ pop esi
+ mov [r6+4],r1
+ pop ebx
+ mov [r6],r0
+ pop ebp
+ mov eax,1
+%ifdef EMMS_ON
+ emms
+%endif
+ ret
+
+; AES (Rijndael) Decryption Subroutine
+
+_aes_dec_blk:
+ push ebp
+ mov ebp,[esp+ctx] ; pointer to context
+ xor eax,eax
+ test [ebp+nblk],byte 2
+ je .0
+ cmp eax,[ebp+nrnd] ; encryption/decryption flags
+ jne short .1
+.0: pop ebp
+ ret
+
+; CAUTION: the order and the values used in these assigns
+; rely on the register mappings
+
+.1: push ebx
+ mov r2,[esp+in_blk+4]
+ push esi
+ mov r3,[ebp+nrnd] ; number of rounds
+ push edi
+ lea r6,[ebp+ksch] ; key pointer
+ mov r0,r3
+ shl r0,4
+ add r6,r0
+
+; input four columns and xor in first round key
+
+ mov r0,[r2]
+ mov r1,[r2+4]
+ mov r4,[r2+8]
+ mov r5,[r2+12]
+ xor r0,[r6]
+ xor r1,[r6+4]
+ xor r4,[r6+8]
+ xor r5,[r6+12]
+
+%ifndef USE_MMX
+ sub esp,8 ; space for register saves on stack
+%endif
+ sub r6,16 ; increment to next round key
+ sub r3,10
+ je .4 ; 10 rounds for 128-bit key
+ sub r6,32
+ sub r3,2
+ je .3 ; 12 rounds for 128-bit key
+ sub r6,32
+
+.2: inv_rnd r6+64 ; 14 rounds for 128-bit key
+ inv_rnd r6+48
+.3: inv_rnd r6+32 ; 12 rounds for 128-bit key
+ inv_rnd r6+16
+.4: inv_rnd r6 ; 10 rounds for 128-bit key
+ inv_rnd r6- 16
+ inv_rnd r6- 32
+ inv_rnd r6- 48
+ inv_rnd r6- 64
+ inv_rnd r6- 80
+ inv_rnd r6- 96
+ inv_rnd r6-112
+ inv_rnd r6-128
+ inv_rnd r6-144,_il_tab ; last round uses a different table
+
+; move final values to the output array. CAUTION: the
+; order of these assigns rely on the register mappings
+
+%ifndef USE_MMX
+ add esp,8
+%endif
+ mov r6,[esp+out_blk+12]
+ mov [r6+12],r5
+ pop edi
+ mov [r6+8],r4
+ pop esi
+ mov [r6+4],r1
+ pop ebx
+ mov [r6],r0
+ pop ebp
+ mov eax,1
+%ifdef EMMS_ON
+ emms
+%endif
+ ret
+
+ end
diff --git a/src/lib/crypto/builtin/aes/aescrypt.c b/src/lib/crypto/builtin/aes/aescrypt.c
new file mode 100644
index 0000000..9db66e2
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aescrypt.c
@@ -0,0 +1,421 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+ 1. distributions of this source code include the above copyright
+ notice, this list of conditions and the following disclaimer;
+
+ 2. distributions in binary form include the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other associated materials;
+
+ 3. the copyright holder's name is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the code for implementing encryption and decryption
+ for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
+ can optionally be replaced by code written in assembler using NASM.
+*/
+
+#include "aesopt.h"
+
+#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7)
+#error An illegal block size has been specified.
+#endif
+
+#define unused 77 /* Sunset Strip */
+
+#define si(y,x,k,c) s(y,c) = word_in(x + 4 * c) ^ k[c]
+#define so(y,x,c) word_out(y + 4 * c, s(x,c))
+
+#if BLOCK_SIZE == 16
+
+#if defined(ARRAYS)
+#define locals(y,x) x[4],y[4]
+#else
+#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
+ /*
+ the following defines prevent the compiler requiring the declaration
+ of generated but unused variables in the fwd_var and inv_var macros
+ */
+#define b04 unused
+#define b05 unused
+#define b06 unused
+#define b07 unused
+#define b14 unused
+#define b15 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
+ s(y,2) = s(x,2); s(y,3) = s(x,3);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
+
+#elif BLOCK_SIZE == 24
+
+#if defined(ARRAYS)
+#define locals(y,x) x[6],y[6]
+#else
+#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5, \
+ y##0,y##1,y##2,y##3,y##4,y##5
+#define b06 unused
+#define b07 unused
+#define b16 unused
+#define b17 unused
+#endif
+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
+ s(y,2) = s(x,2); s(y,3) = s(x,3); \
+ s(y,4) = s(x,4); s(y,5) = s(x,5);
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \
+ si(y,x,k,3); si(y,x,k,4); si(y,x,k,5)
+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \
+ so(y,x,3); so(y,x,4); so(y,x,5)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \
+ rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5)
+#else
+
+#if defined(ARRAYS)
+#define locals(y,x) x[8],y[8]
+#else
+#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \
+ y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7
+#endif
+#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
+ s(y,2) = s(x,2); s(y,3) = s(x,3); \
+ s(y,4) = s(x,4); s(y,5) = s(x,5); \
+ s(y,6) = s(x,6); s(y,7) = s(x,7);
+
+#if BLOCK_SIZE == 32
+
+#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \
+ si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7)
+#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \
+ so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7)
+#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \
+ rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7)
+#else
+
+#define state_in(y,x,k) \
+switch(nc) \
+{ case 8: si(y,x,k,7); si(y,x,k,6); \
+ case 6: si(y,x,k,5); si(y,x,k,4); \
+ case 4: si(y,x,k,3); si(y,x,k,2); \
+ si(y,x,k,1); si(y,x,k,0); \
+}
+
+#define state_out(y,x) \
+switch(nc) \
+{ case 8: so(y,x,7); so(y,x,6); \
+ case 6: so(y,x,5); so(y,x,4); \
+ case 4: so(y,x,3); so(y,x,2); \
+ so(y,x,1); so(y,x,0); \
+}
+
+#if defined(FAST_VARIABLE)
+
+#define round(rm,y,x,k) \
+switch(nc) \
+{ case 8: rm(y,x,k,7); rm(y,x,k,6); \
+ rm(y,x,k,5); rm(y,x,k,4); \
+ rm(y,x,k,3); rm(y,x,k,2); \
+ rm(y,x,k,1); rm(y,x,k,0); \
+ break; \
+ case 6: rm(y,x,k,5); rm(y,x,k,4); \
+ rm(y,x,k,3); rm(y,x,k,2); \
+ rm(y,x,k,1); rm(y,x,k,0); \
+ break; \
+ case 4: rm(y,x,k,3); rm(y,x,k,2); \
+ rm(y,x,k,1); rm(y,x,k,0); \
+ break; \
+}
+#else
+
+#define round(rm,y,x,k) \
+switch(nc) \
+{ case 8: rm(y,x,k,7); rm(y,x,k,6); \
+ case 6: rm(y,x,k,5); rm(y,x,k,4); \
+ case 4: rm(y,x,k,3); rm(y,x,k,2); \
+ rm(y,x,k,1); rm(y,x,k,0); \
+}
+
+#endif
+
+#endif
+#endif
+
+#if defined(ENCRYPTION)
+
+/* I am grateful to Frank Yellin for the following construction
+ (and that for decryption) which, given the column (c) of the
+ output state variable, gives the input state variables which
+ are needed in its computation for each row (r) of the state.
+
+ For the fixed block size options, compilers should be able to
+ reduce this complex expression (and the equivalent one for
+ decryption) to a static variable reference at compile time.
+ But for variable block size code, there will be some limbs on
+ which conditional clauses will be returned.
+*/
+
+/* y = output word, x = input word, r = row, c = column for r = 0,
+ 1, 2 and 3 = column accessed for row r.
+*/
+
+#define fwd_var(x,r,c) \
+ ( r==0 ? \
+ ( c==0 ? s(x,0) \
+ : c==1 ? s(x,1) \
+ : c==2 ? s(x,2) \
+ : c==3 ? s(x,3) \
+ : c==4 ? s(x,4) \
+ : c==5 ? s(x,5) \
+ : c==6 ? s(x,6) \
+ : s(x,7)) \
+ : r==1 ? \
+ ( c==0 ? s(x,1) \
+ : c==1 ? s(x,2) \
+ : c==2 ? s(x,3) \
+ : c==3 ? nc==4 ? s(x,0) : s(x,4) \
+ : c==4 ? s(x,5) \
+ : c==5 ? nc==8 ? s(x,6) : s(x,0) \
+ : c==6 ? s(x,7) \
+ : s(x,0)) \
+ : r==2 ? \
+ ( c==0 ? nc==8 ? s(x,3) : s(x,2) \
+ : c==1 ? nc==8 ? s(x,4) : s(x,3) \
+ : c==2 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \
+ : c==3 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \
+ : c==4 ? nc==8 ? s(x,7) : s(x,0) \
+ : c==5 ? nc==8 ? s(x,0) : s(x,1) \
+ : c==6 ? s(x,1) \
+ : s(x,2)) \
+ : \
+ ( c==0 ? nc==8 ? s(x,4) : s(x,3) \
+ : c==1 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \
+ : c==2 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \
+ : c==3 ? nc==4 ? s(x,2) : nc==8 ? s(x,7) : s(x,0) \
+ : c==4 ? nc==8 ? s(x,0) : s(x,1) \
+ : c==5 ? nc==8 ? s(x,1) : s(x,2) \
+ : c==6 ? s(x,2) \
+ : s(x,3)))
+
+#if defined(FT4_SET)
+#undef dec_fmvars
+#define dec_fmvars
+#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c)
+#elif defined(FT1_SET)
+#undef dec_fmvars
+#define dec_fmvars
+#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c)
+#else
+#define fwd_rnd(y,x,k,c) s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c]
+#endif
+
+#if defined(FL4_SET)
+#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c)
+#elif defined(FL1_SET)
+#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c)
+#else
+#define fwd_lrnd(y,x,k,c) s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c]
+#endif
+
+aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])
+{ uint32_t locals(b0, b1);
+ const uint32_t *kp = cx->k_sch;
+ dec_fmvars /* declare variables for fwd_mcol() if needed */
+
+ if(!(cx->n_blk & 1)) return aes_bad;
+
+ state_in(b0, in_blk, kp);
+
+#if (ENC_UNROLL == FULL)
+
+ kp += (cx->n_rnd - 9) * nc;
+
+ switch(cx->n_rnd)
+ {
+ case 14: round(fwd_rnd, b1, b0, kp - 4 * nc);
+ round(fwd_rnd, b0, b1, kp - 3 * nc);
+ case 12: round(fwd_rnd, b1, b0, kp - 2 * nc);
+ round(fwd_rnd, b0, b1, kp - nc);
+ case 10: round(fwd_rnd, b1, b0, kp );
+ round(fwd_rnd, b0, b1, kp + nc);
+ round(fwd_rnd, b1, b0, kp + 2 * nc);
+ round(fwd_rnd, b0, b1, kp + 3 * nc);
+ round(fwd_rnd, b1, b0, kp + 4 * nc);
+ round(fwd_rnd, b0, b1, kp + 5 * nc);
+ round(fwd_rnd, b1, b0, kp + 6 * nc);
+ round(fwd_rnd, b0, b1, kp + 7 * nc);
+ round(fwd_rnd, b1, b0, kp + 8 * nc);
+ round(fwd_lrnd, b0, b1, kp + 9 * nc);
+ }
+#else
+
+#if (ENC_UNROLL == PARTIAL)
+ { uint32_t rnd;
+ for(rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd)
+ {
+ kp += nc;
+ round(fwd_rnd, b1, b0, kp);
+ kp += nc;
+ round(fwd_rnd, b0, b1, kp);
+ }
+ kp += nc;
+ round(fwd_rnd, b1, b0, kp);
+#else
+ { uint32_t rnd, *p0 = b0, *p1 = b1, *pt;
+ for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd)
+ {
+ kp += nc;
+ round(fwd_rnd, p1, p0, kp);
+ pt = p0, p0 = p1, p1 = pt;
+ }
+#endif
+ kp += nc;
+ round(fwd_lrnd, b0, b1, kp);
+ }
+#endif
+
+ state_out(out_blk, b0);
+ return aes_good;
+}
+
+#endif
+
+#if defined(DECRYPTION)
+
+#define inv_var(x,r,c) \
+ ( r==0 ? \
+ ( c==0 ? s(x,0) \
+ : c==1 ? s(x,1) \
+ : c==2 ? s(x,2) \
+ : c==3 ? s(x,3) \
+ : c==4 ? s(x,4) \
+ : c==5 ? s(x,5) \
+ : c==6 ? s(x,6) \
+ : s(x,7)) \
+ : r==1 ? \
+ ( c==0 ? nc==4 ? s(x,3) : nc==8 ? s(x,7) : s(x,5) \
+ : c==1 ? s(x,0) \
+ : c==2 ? s(x,1) \
+ : c==3 ? s(x,2) \
+ : c==4 ? s(x,3) \
+ : c==5 ? s(x,4) \
+ : c==6 ? s(x,5) \
+ : s(x,6)) \
+ : r==2 ? \
+ ( c==0 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \
+ : c==1 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \
+ : c==2 ? nc==8 ? s(x,7) : s(x,0) \
+ : c==3 ? nc==8 ? s(x,0) : s(x,1) \
+ : c==4 ? nc==8 ? s(x,1) : s(x,2) \
+ : c==5 ? nc==8 ? s(x,2) : s(x,3) \
+ : c==6 ? s(x,3) \
+ : s(x,4)) \
+ : \
+ ( c==0 ? nc==4 ? s(x,1) : nc==8 ? s(x,4) : s(x,3) \
+ : c==1 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \
+ : c==2 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \
+ : c==3 ? nc==8 ? s(x,7) : s(x,0) \
+ : c==4 ? nc==8 ? s(x,0) : s(x,1) \
+ : c==5 ? nc==8 ? s(x,1) : s(x,2) \
+ : c==6 ? s(x,2) \
+ : s(x,3)))
+
+#if defined(IT4_SET)
+#undef dec_imvars
+#define dec_imvars
+#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c)
+#elif defined(IT1_SET)
+#undef dec_imvars
+#define dec_imvars
+#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c)
+#else
+#define inv_rnd(y,x,k,c) s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c])
+#endif
+
+#if defined(IL4_SET)
+#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c)
+#elif defined(IL1_SET)
+#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c)
+#else
+#define inv_lrnd(y,x,k,c) s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]
+#endif
+
+aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])
+{ uint32_t locals(b0, b1);
+ const uint32_t *kp = cx->k_sch + nc * cx->n_rnd;
+ dec_imvars /* declare variables for inv_mcol() if needed */
+
+ if(!(cx->n_blk & 2)) return aes_bad;
+
+ state_in(b0, in_blk, kp);
+
+#if (DEC_UNROLL == FULL)
+
+ kp = cx->k_sch + 9 * nc;
+ switch(cx->n_rnd)
+ {
+ case 14: round(inv_rnd, b1, b0, kp + 4 * nc);
+ round(inv_rnd, b0, b1, kp + 3 * nc);
+ case 12: round(inv_rnd, b1, b0, kp + 2 * nc);
+ round(inv_rnd, b0, b1, kp + nc );
+ case 10: round(inv_rnd, b1, b0, kp );
+ round(inv_rnd, b0, b1, kp - nc);
+ round(inv_rnd, b1, b0, kp - 2 * nc);
+ round(inv_rnd, b0, b1, kp - 3 * nc);
+ round(inv_rnd, b1, b0, kp - 4 * nc);
+ round(inv_rnd, b0, b1, kp - 5 * nc);
+ round(inv_rnd, b1, b0, kp - 6 * nc);
+ round(inv_rnd, b0, b1, kp - 7 * nc);
+ round(inv_rnd, b1, b0, kp - 8 * nc);
+ round(inv_lrnd, b0, b1, kp - 9 * nc);
+ }
+#else
+
+#if (DEC_UNROLL == PARTIAL)
+ { uint32_t rnd;
+ for(rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd)
+ {
+ kp -= nc;
+ round(inv_rnd, b1, b0, kp);
+ kp -= nc;
+ round(inv_rnd, b0, b1, kp);
+ }
+ kp -= nc;
+ round(inv_rnd, b1, b0, kp);
+#else
+ { uint32_t rnd, *p0 = b0, *p1 = b1, *pt;
+ for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd)
+ {
+ kp -= nc;
+ round(inv_rnd, p1, p0, kp);
+ pt = p0, p0 = p1, p1 = pt;
+ }
+#endif
+ kp -= nc;
+ round(inv_lrnd, b0, b1, kp);
+ }
+#endif
+
+ state_out(out_blk, b0);
+ return aes_good;
+}
+
+#endif
diff --git a/src/lib/crypto/builtin/aes/aeskey.c b/src/lib/crypto/builtin/aes/aeskey.c
new file mode 100644
index 0000000..60f766b
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aeskey.c
@@ -0,0 +1,369 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+ 1. distributions of this source code include the above copyright
+ notice, this list of conditions and the following disclaimer;
+
+ 2. distributions in binary form include the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other associated materials;
+
+ 3. the copyright holder's name is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the code for implementing the key schedule for AES
+ (Rijndael) for block and key sizes of 16, 24, and 32 bytes.
+*/
+
+#include "aesopt.h"
+
+#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7)
+#error An illegal block size has been specified.
+#endif
+
+/* Subroutine to set the block size (if variable) in bytes, legal
+ values being 16, 24 and 32.
+*/
+
+#if !defined(BLOCK_SIZE) && defined(SET_BLOCK_LENGTH)
+
+aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1])
+{
+#if !defined(FIXED_TABLES)
+ if(!tab_init) gen_tabs();
+#endif
+
+ if((blen & 7) || blen < 16 || blen > 32)
+ {
+ cx->n_blk = 0; return aes_bad;
+ }
+
+ cx->n_blk = blen;
+ return aes_good;
+}
+
+#endif
+
+/* Initialise the key schedule from the user supplied key. The key
+ length is now specified in bytes - 16, 24 or 32 as appropriate.
+ This corresponds to bit lengths of 128, 192 and 256 bits, and
+ to Nk values of 4, 6 and 8 respectively.
+
+ The following macros implement a single cycle in the key
+ schedule generation process. The number of cycles needed
+ for each cx->n_col and nk value is:
+
+ nk = 4 5 6 7 8
+ ------------------------------
+ cx->n_col = 4 10 9 8 7 7
+ cx->n_col = 5 14 11 10 9 9
+ cx->n_col = 6 19 15 12 11 11
+ cx->n_col = 7 21 19 16 13 14
+ cx->n_col = 8 29 23 19 17 14
+*/
+
+#if defined(ENCRYPTION_KEY_SCHEDULE)
+
+#define ke4(k,i) \
+{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
+ k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
+}
+#define kel4(k,i) \
+{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
+ k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
+}
+
+#define ke6(k,i) \
+{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
+ k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
+ k[6*(i)+10] = ss[4] ^= ss[3]; k[6*(i)+11] = ss[5] ^= ss[4]; \
+}
+#define kel6(k,i) \
+{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
+ k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
+}
+
+#define ke8(k,i) \
+{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
+ k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
+ k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); k[8*(i)+13] = ss[5] ^= ss[4]; \
+ k[8*(i)+14] = ss[6] ^= ss[5]; k[8*(i)+15] = ss[7] ^= ss[6]; \
+}
+#define kel8(k,i) \
+{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
+ k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
+}
+
+aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1])
+{ uint32_t ss[8];
+
+#if !defined(FIXED_TABLES)
+ if(!tab_init) gen_tabs();
+#endif
+
+#if !defined(BLOCK_SIZE)
+ if(!cx->n_blk) cx->n_blk = 16;
+#else
+ cx->n_blk = BLOCK_SIZE;
+#endif
+
+ cx->n_blk = (cx->n_blk & ~3U) | 1;
+
+ cx->k_sch[0] = ss[0] = word_in(in_key );
+ cx->k_sch[1] = ss[1] = word_in(in_key + 4);
+ cx->k_sch[2] = ss[2] = word_in(in_key + 8);
+ cx->k_sch[3] = ss[3] = word_in(in_key + 12);
+
+#if (BLOCK_SIZE == 16) && (ENC_UNROLL != NONE)
+
+ switch(klen)
+ {
+ case 16: ke4(cx->k_sch, 0); ke4(cx->k_sch, 1);
+ ke4(cx->k_sch, 2); ke4(cx->k_sch, 3);
+ ke4(cx->k_sch, 4); ke4(cx->k_sch, 5);
+ ke4(cx->k_sch, 6); ke4(cx->k_sch, 7);
+ ke4(cx->k_sch, 8); kel4(cx->k_sch, 9);
+ cx->n_rnd = 10; break;
+ case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+ cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+ ke6(cx->k_sch, 0); ke6(cx->k_sch, 1);
+ ke6(cx->k_sch, 2); ke6(cx->k_sch, 3);
+ ke6(cx->k_sch, 4); ke6(cx->k_sch, 5);
+ ke6(cx->k_sch, 6); kel6(cx->k_sch, 7);
+ cx->n_rnd = 12; break;
+ case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+ cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+ cx->k_sch[6] = ss[6] = word_in(in_key + 24);
+ cx->k_sch[7] = ss[7] = word_in(in_key + 28);
+ ke8(cx->k_sch, 0); ke8(cx->k_sch, 1);
+ ke8(cx->k_sch, 2); ke8(cx->k_sch, 3);
+ ke8(cx->k_sch, 4); ke8(cx->k_sch, 5);
+ kel8(cx->k_sch, 6);
+ cx->n_rnd = 14; break;
+ default: cx->n_rnd = 0; return aes_bad;
+ }
+#else
+ { uint32_t i, l;
+ cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+ l = (nc * cx->n_rnd + nc - 1) / (klen >> 2);
+
+ switch(klen)
+ {
+ case 16: for(i = 0; i < l; ++i)
+ ke4(cx->k_sch, i);
+ break;
+ case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+ cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+ for(i = 0; i < l; ++i)
+ ke6(cx->k_sch, i);
+ break;
+ case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+ cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+ cx->k_sch[6] = ss[6] = word_in(in_key + 24);
+ cx->k_sch[7] = ss[7] = word_in(in_key + 28);
+ for(i = 0; i < l; ++i)
+ ke8(cx->k_sch, i);
+ break;
+ default: cx->n_rnd = 0; return aes_bad;
+ }
+ }
+#endif
+
+ return aes_good;
+}
+
+#endif
+
+#if defined(DECRYPTION_KEY_SCHEDULE)
+
+#if (DEC_ROUND != NO_TABLES)
+#define d_vars dec_imvars
+#define ff(x) inv_mcol(x)
+#else
+#define ff(x) (x)
+#define d_vars
+#endif
+
+#if 1
+#define kdf4(k,i) \
+{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; ss[1] = ss[1] ^ ss[3]; ss[2] = ss[2] ^ ss[3]; ss[3] = ss[3]; \
+ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; \
+ ss[4] ^= k[4*(i)]; k[4*(i)+4] = ff(ss[4]); ss[4] ^= k[4*(i)+1]; k[4*(i)+5] = ff(ss[4]); \
+ ss[4] ^= k[4*(i)+2]; k[4*(i)+6] = ff(ss[4]); ss[4] ^= k[4*(i)+3]; k[4*(i)+7] = ff(ss[4]); \
+}
+#define kd4(k,i) \
+{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \
+ k[4*(i)+4] = ss[4] ^= k[4*(i)]; k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \
+ k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \
+}
+#define kdl4(k,i) \
+{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; \
+ k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; k[4*(i)+5] = ss[1] ^ ss[3]; \
+ k[4*(i)+6] = ss[0]; k[4*(i)+7] = ss[1]; \
+}
+#else
+#define kdf4(k,i) \
+{ ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+ 4] = ff(ss[0]); ss[1] ^= ss[0]; k[4*(i)+ 5] = ff(ss[1]); \
+ ss[2] ^= ss[1]; k[4*(i)+ 6] = ff(ss[2]); ss[3] ^= ss[2]; k[4*(i)+ 7] = ff(ss[3]); \
+}
+#define kd4(k,i) \
+{ ss[4] = ls_box(ss[3],3) ^ rcon_tab[i]; \
+ ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[4*(i)+ 4] = ss[4] ^= k[4*(i)]; \
+ ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[4] ^= k[4*(i)+ 1]; \
+ ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[4] ^= k[4*(i)+ 2]; \
+ ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[4] ^= k[4*(i)+ 3]; \
+}
+#define kdl4(k,i) \
+{ ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+ 4] = ss[0]; ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[1]; \
+ ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[2]; ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[3]; \
+}
+#endif
+
+#define kdf6(k,i) \
+{ ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 6] = ff(ss[0]); ss[1] ^= ss[0]; k[6*(i)+ 7] = ff(ss[1]); \
+ ss[2] ^= ss[1]; k[6*(i)+ 8] = ff(ss[2]); ss[3] ^= ss[2]; k[6*(i)+ 9] = ff(ss[3]); \
+ ss[4] ^= ss[3]; k[6*(i)+10] = ff(ss[4]); ss[5] ^= ss[4]; k[6*(i)+11] = ff(ss[5]); \
+}
+#define kd6(k,i) \
+{ ss[6] = ls_box(ss[5],3) ^ rcon_tab[i]; \
+ ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \
+ ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \
+ ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \
+ ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \
+ ss[4] ^= ss[3]; k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \
+ ss[5] ^= ss[4]; k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \
+}
+#define kdl6(k,i) \
+{ ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 6] = ss[0]; ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[1]; \
+ ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[2]; ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[3]; \
+}
+
+#define kdf8(k,i) \
+{ ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 8] = ff(ss[0]); ss[1] ^= ss[0]; k[8*(i)+ 9] = ff(ss[1]); \
+ ss[2] ^= ss[1]; k[8*(i)+10] = ff(ss[2]); ss[3] ^= ss[2]; k[8*(i)+11] = ff(ss[3]); \
+ ss[4] ^= ls_box(ss[3],0); k[8*(i)+12] = ff(ss[4]); ss[5] ^= ss[4]; k[8*(i)+13] = ff(ss[5]); \
+ ss[6] ^= ss[5]; k[8*(i)+14] = ff(ss[6]); ss[7] ^= ss[6]; k[8*(i)+15] = ff(ss[7]); \
+}
+#define kd8(k,i) \
+{ uint32_t g = ls_box(ss[7],3) ^ rcon_tab[i]; \
+ ss[0] ^= g; g = ff(g); k[8*(i)+ 8] = g ^= k[8*(i)]; \
+ ss[1] ^= ss[0]; k[8*(i)+ 9] = g ^= k[8*(i)+ 1]; \
+ ss[2] ^= ss[1]; k[8*(i)+10] = g ^= k[8*(i)+ 2]; \
+ ss[3] ^= ss[2]; k[8*(i)+11] = g ^= k[8*(i)+ 3]; \
+ g = ls_box(ss[3],0); \
+ ss[4] ^= g; g = ff(g); k[8*(i)+12] = g ^= k[8*(i)+ 4]; \
+ ss[5] ^= ss[4]; k[8*(i)+13] = g ^= k[8*(i)+ 5]; \
+ ss[6] ^= ss[5]; k[8*(i)+14] = g ^= k[8*(i)+ 6]; \
+ ss[7] ^= ss[6]; k[8*(i)+15] = g ^= k[8*(i)+ 7]; \
+}
+#define kdl8(k,i) \
+{ ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 8] = ss[0]; ss[1] ^= ss[0]; k[8*(i)+ 9] = ss[1]; \
+ ss[2] ^= ss[1]; k[8*(i)+10] = ss[2]; ss[3] ^= ss[2]; k[8*(i)+11] = ss[3]; \
+}
+
+aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1])
+{ uint32_t ss[8];
+ d_vars
+
+#if !defined(FIXED_TABLES)
+ if(!tab_init) gen_tabs();
+#endif
+
+#if !defined(BLOCK_SIZE)
+ if(!cx->n_blk) cx->n_blk = 16;
+#else
+ cx->n_blk = BLOCK_SIZE;
+#endif
+
+ cx->n_blk = (cx->n_blk & ~3U) | 2;
+
+ cx->k_sch[0] = ss[0] = word_in(in_key );
+ cx->k_sch[1] = ss[1] = word_in(in_key + 4);
+ cx->k_sch[2] = ss[2] = word_in(in_key + 8);
+ cx->k_sch[3] = ss[3] = word_in(in_key + 12);
+
+#if (BLOCK_SIZE == 16) && (DEC_UNROLL != NONE)
+
+ switch(klen)
+ {
+ case 16: kdf4(cx->k_sch, 0); kd4(cx->k_sch, 1);
+ kd4(cx->k_sch, 2); kd4(cx->k_sch, 3);
+ kd4(cx->k_sch, 4); kd4(cx->k_sch, 5);
+ kd4(cx->k_sch, 6); kd4(cx->k_sch, 7);
+ kd4(cx->k_sch, 8); kdl4(cx->k_sch, 9);
+ cx->n_rnd = 10; break;
+ case 24: ss[4] = word_in(in_key + 16);
+ cx->k_sch[4] = ff(ss[4]);
+ ss[5] = word_in(in_key + 20);
+ cx->k_sch[5] = ff(ss[5]);
+ kdf6(cx->k_sch, 0); kd6(cx->k_sch, 1);
+ kd6(cx->k_sch, 2); kd6(cx->k_sch, 3);
+ kd6(cx->k_sch, 4); kd6(cx->k_sch, 5);
+ kd6(cx->k_sch, 6); kdl6(cx->k_sch, 7);
+ cx->n_rnd = 12; break;
+ case 32: ss[4] = word_in(in_key + 16);
+ cx->k_sch[4] = ff(ss[4]);
+ ss[5] = word_in(in_key + 20);
+ cx->k_sch[5] = ff(ss[5]);
+ ss[6] = word_in(in_key + 24);
+ cx->k_sch[6] = ff(ss[6]);
+ ss[7] = word_in(in_key + 28);
+ cx->k_sch[7] = ff(ss[7]);
+ kdf8(cx->k_sch, 0); kd8(cx->k_sch, 1);
+ kd8(cx->k_sch, 2); kd8(cx->k_sch, 3);
+ kd8(cx->k_sch, 4); kd8(cx->k_sch, 5);
+ kdl8(cx->k_sch, 6);
+ cx->n_rnd = 14; break;
+ default: cx->n_rnd = 0; return aes_bad;
+ }
+#else
+ { uint32_t i, l;
+ cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+ l = (nc * cx->n_rnd + nc - 1) / (klen >> 2);
+
+ switch(klen)
+ {
+ case 16:
+ for(i = 0; i < l; ++i)
+ ke4(cx->k_sch, i);
+ break;
+ case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+ cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+ for(i = 0; i < l; ++i)
+ ke6(cx->k_sch, i);
+ break;
+ case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16);
+ cx->k_sch[5] = ss[5] = word_in(in_key + 20);
+ cx->k_sch[6] = ss[6] = word_in(in_key + 24);
+ cx->k_sch[7] = ss[7] = word_in(in_key + 28);
+ for(i = 0; i < l; ++i)
+ ke8(cx->k_sch, i);
+ break;
+ default: cx->n_rnd = 0; return aes_bad;
+ }
+#if (DEC_ROUND != NO_TABLES)
+ for(i = nc; i < nc * cx->n_rnd; ++i)
+ cx->k_sch[i] = inv_mcol(cx->k_sch[i]);
+#endif
+ }
+#endif
+
+ return aes_good;
+}
+
+#endif
diff --git a/src/lib/crypto/builtin/aes/aeskeypp.c b/src/lib/crypto/builtin/aes/aeskeypp.c
new file mode 100644
index 0000000..89fd900
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aeskeypp.c
@@ -0,0 +1,399 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+ 1. distributions of this source code include the above copyright
+ notice, this list of conditions and the following disclaimer;
+
+ 2. distributions in binary form include the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other associated materials;
+
+ 3. the copyright holder's name is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 21/01/2002
+
+ This file contains the code for implementing the key schedule for AES
+ (Rijndael) for block and key sizes of 16, 20, 24, 28 and 32 bytes.
+*/
+
+#include "aesopt.h"
+
+/* Subroutine to set the block size (if variable) in bytes, legal
+ values being 16, 24 and 32.
+*/
+
+#if !defined(BLOCK_SIZE) && defined(SET_BLOCK_LENGTH)
+
+/* Subroutine to set the block size (if variable) in bytes, legal
+ values being 16, 24 and 32.
+*/
+
+aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1])
+{
+#if !defined(FIXED_TABLES)
+ if(!tab_init) gen_tabs();
+#endif
+
+ if((blen & 3) || blen < 16 || blen > 32)
+ {
+ cx->n_blk = 0; return aes_bad;
+ }
+
+ cx->n_blk = blen;
+ return aes_good;
+}
+
+#endif
+
+/* Initialise the key schedule from the user supplied key. The key
+ length is now specified in bytes - 16, 24 or 32 as appropriate.
+ This corresponds to bit lengths of 128, 192 and 256 bits, and
+ to Nk values of 4, 6 and 8 respectively.
+
+ The following macros implement a single cycle in the key
+ schedule generation process. The number of cycles needed
+ for each cx->n_blk and nk value is:
+
+ nk = 4 5 6 7 8
+ ------------------------------
+ cx->n_blk = 4 10 9 8 7 7
+ cx->n_blk = 5 14 11 10 9 9
+ cx->n_blk = 6 19 15 12 11 11
+ cx->n_blk = 7 21 19 16 13 14
+ cx->n_blk = 8 29 23 19 17 14
+*/
+
+/* Initialise the key schedule from the user supplied key. The key
+ length is now specified in bytes - 16, 20, 24, 28 or 32 as
+ appropriate. This corresponds to bit lengths of 128, 160, 192,
+ 224 and 256 bits, and to Nk values of 4, 5, 6, 7 & 8 respectively.
+ */
+
+#define mx(t,f) (*t++ = inv_mcol(*f),f++)
+#define cp(t,f) *t++ = *f++
+
+#if BLOCK_SIZE == 16
+#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s)
+#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s)
+#elif BLOCK_SIZE == 20
+#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
+ cp(d,s)
+#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
+ mx(d,s)
+#elif BLOCK_SIZE == 24
+#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
+ cp(d,s); cp(d,s)
+#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
+ mx(d,s); mx(d,s)
+#elif BLOCK_SIZE == 28
+#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
+ cp(d,s); cp(d,s); cp(d,s)
+#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
+ mx(d,s); mx(d,s); mx(d,s)
+#elif BLOCK_SIZE == 32
+#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \
+ cp(d,s); cp(d,s); cp(d,s); cp(d,s)
+#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
+ mx(d,s); mx(d,s); mx(d,s); mx(d,s)
+#else
+
+#define cpy(d,s) \
+switch(nc) \
+{ case 8: cp(d,s); \
+ case 7: cp(d,s); \
+ case 6: cp(d,s); \
+ case 5: cp(d,s); \
+ case 4: cp(d,s); cp(d,s); \
+ cp(d,s); cp(d,s); \
+}
+
+#define mix(d,s) \
+switch(nc) \
+{ case 8: mx(d,s); \
+ case 7: mx(d,s); \
+ case 6: mx(d,s); \
+ case 5: mx(d,s); \
+ case 4: mx(d,s); mx(d,s); \
+ mx(d,s); mx(d,s); \
+}
+
+#endif
+
+/* The following macros implement a single cycle in the key
+ schedule generation process. The number of cycles needed
+ for each cx->n_blk and nk value is:
+
+ nk = 4 5 6 7 8
+ -----------------------
+ cx->n_blk = 4 10 9 8 7 7
+ cx->n_blk = 5 14 11 10 9 9
+ cx->n_blk = 6 19 15 12 11 11
+ cx->n_blk = 7 21 19 16 13 14
+ cx->n_blk = 8 29 23 19 17 14
+*/
+
+#define ks4(i) \
+{ p ^= ls_box(s,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \
+ cx->k_sch[4*(i)+4] = p; \
+ cx->k_sch[4*(i)+5] = q; \
+ cx->k_sch[4*(i)+6] = r; \
+ cx->k_sch[4*(i)+7] = s; \
+}
+
+#define ks5(i) \
+{ p ^= ls_box(t,3) ^ rcon_tab[i]; q ^= p; \
+ r ^= q; s ^= r; t ^= s; \
+ cx->k_sch[5*(i)+ 5] = p; \
+ cx->k_sch[5*(i)+ 6] = q; \
+ cx->k_sch[5*(i)+ 7] = r; \
+ cx->k_sch[5*(i)+ 8] = s; \
+ cx->k_sch[5*(i)+ 9] = t; \
+}
+
+#define ks6(i) \
+{ p ^= ls_box(u,3) ^ rcon_tab[i]; q ^= p; \
+ r ^= q; s ^= r; t ^= s; u ^= t; \
+ cx->k_sch[6*(i)+ 6] = p; \
+ cx->k_sch[6*(i)+ 7] = q; \
+ cx->k_sch[6*(i)+ 8] = r; \
+ cx->k_sch[6*(i)+ 9] = s; \
+ cx->k_sch[6*(i)+10] = t; \
+ cx->k_sch[6*(i)+11] = u; \
+}
+
+#define ks7(i) \
+{ p ^= ls_box(v,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \
+ t ^= ls_box(s,0); u ^= t; v ^= u; \
+ cx->k_sch[7*(i)+ 7] = p; \
+ cx->k_sch[7*(i)+ 8] = q; \
+ cx->k_sch[7*(i)+ 9] = r; \
+ cx->k_sch[7*(i)+10] = s; \
+ cx->k_sch[7*(i)+11] = t; \
+ cx->k_sch[7*(i)+12] = u; \
+ cx->k_sch[7*(i)+13] = v; \
+}
+
+#define ks8(i) \
+{ p ^= ls_box(w,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \
+ t ^= ls_box(s,0); u ^= t; v ^= u; w ^= v; \
+ cx->k_sch[8*(i)+ 8] = p; \
+ cx->k_sch[8*(i)+ 9] = q; \
+ cx->k_sch[8*(i)+10] = r; \
+ cx->k_sch[8*(i)+11] = s; \
+ cx->k_sch[8*(i)+12] = t; \
+ cx->k_sch[8*(i)+13] = u; \
+ cx->k_sch[8*(i)+14] = v; \
+ cx->k_sch[8*(i)+15] = w; \
+}
+
+#if defined(ENCRYPTION_KEY_SCHEDULE)
+
+aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1])
+{ uint32_t i,p,q,r,s,t,u,v,w;
+
+#if !defined(FIXED_TABLES)
+ if(!tab_init) gen_tabs();
+#endif
+
+#if !defined(BLOCK_SIZE)
+ if(!cx->n_blk) cx->n_blk = 16;
+#else
+ cx->n_blk = BLOCK_SIZE;
+#endif
+
+ cx->n_blk = (cx->n_blk & ~3) | 1;
+ cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+
+ cx->k_sch[0] = p = word_in(in_key );
+ cx->k_sch[1] = q = word_in(in_key + 4);
+ cx->k_sch[2] = r = word_in(in_key + 8);
+ cx->k_sch[3] = s = word_in(in_key + 12);
+
+#if BLOCK_SIZE == 16 && defined(UNROLL)
+
+ switch(klen >> 2)
+ {
+ case 4: ks4(0); ks4(1); ks4(2); ks4(3);
+ ks4(4); ks4(5); ks4(6); ks4(7);
+ ks4(8); ks4(9);
+ cx->n_rnd = 10; break;
+ case 5: cx->k_sch[4] = t = word_in(in_key + 16);
+ ks5(0); ks5(1); ks5(2); ks5(3);
+ ks5(4); ks5(5); ks5(6); ks5(7);
+ ks5(8);
+ cx->n_rnd = 11; break;
+ case 6: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ ks6(0); ks6(1); ks6(2); ks6(3);
+ ks6(4); ks6(5); ks6(6); ks6(7);
+ cx->n_rnd = 12; break;
+ case 7: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ cx->k_sch[6] = v = word_in(in_key + 24);
+ ks7(0); ks7(1); ks7(2); ks7(3);
+ ks7(4); ks7(5); ks7(6);
+ cx->n_rnd = 13; break;
+ case 8: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ cx->k_sch[6] = v = word_in(in_key + 24);
+ cx->k_sch[7] = w = word_in(in_key + 28);
+ ks8(0); ks8(1); ks8(2); ks8(3);
+ ks8(4); ks8(5); ks8(6);
+ cx->n_rnd = 14; break;
+ default:cx->n_rnd = 0; return aes_bad;
+ }
+#else
+ cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+ {
+ uint32_t l = (nc * (cx->n_rnd + 1) - 1) / (klen >> 2);
+ switch(klen >> 2)
+ {
+ case 4: for(i = 0; i < l; ++i)
+ ks4(i);
+ break;
+ case 5: cx->k_sch[4] = t = word_in(in_key + 16);
+ for(i = 0; i < l; ++i)
+ ks5(i);
+ break;
+ case 6: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ for(i = 0; i < l; ++i)
+ ks6(i);
+ break;
+ case 7: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ cx->k_sch[6] = v = word_in(in_key + 24);
+ for(i = 0; i < l; ++i)
+ ks7(i);
+ break;
+ case 8: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ cx->k_sch[6] = v = word_in(in_key + 24);
+ cx->k_sch[7] = w = word_in(in_key + 28);
+ for(i = 0; i < l; ++i)
+ ks8(i);
+ break;
+ }
+ }
+#endif
+
+ return aes_good;
+}
+
+#endif
+
+#if defined(DECRYPTION_KEY_SCHEDULE)
+
+aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1])
+{ uint32_t i,p,q,r,s,t,u,v,w;
+ dec_imvars
+
+#if !defined(FIXED_TABLES)
+ if(!tab_init) gen_tabs();
+#endif
+
+#if !defined(BLOCK_SIZE)
+ if(!cx->n_blk) cx->n_blk = 16;
+#else
+ cx->n_blk = BLOCK_SIZE;
+#endif
+
+ cx->n_blk = (cx->n_blk & ~3) | 2;
+ cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+
+ cx->k_sch[0] = p = word_in(in_key );
+ cx->k_sch[1] = q = word_in(in_key + 4);
+ cx->k_sch[2] = r = word_in(in_key + 8);
+ cx->k_sch[3] = s = word_in(in_key + 12);
+
+#if BLOCK_SIZE == 16 && defined(UNROLL)
+
+ switch(klen >> 2)
+ {
+ case 4: ks4(0); ks4(1); ks4(2); ks4(3);
+ ks4(4); ks4(5); ks4(6); ks4(7);
+ ks4(8); ks4(9);
+ cx->n_rnd = 10; break;
+ case 5: cx->k_sch[4] = t = word_in(in_key + 16);
+ ks5(0); ks5(1); ks5(2); ks5(3);
+ ks5(4); ks5(5); ks5(6); ks5(7);
+ ks5(8);
+ cx->n_rnd = 11; break;
+ case 6: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ ks6(0); ks6(1); ks6(2); ks6(3);
+ ks6(4); ks6(5); ks6(6); ks6(7);
+ cx->n_rnd = 12; break;
+ case 7: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ cx->k_sch[6] = v = word_in(in_key + 24);
+ ks7(0); ks7(1); ks7(2); ks7(3);
+ ks7(4); ks7(5); ks7(6);
+ cx->n_rnd = 13; break;
+ case 8: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ cx->k_sch[6] = v = word_in(in_key + 24);
+ cx->k_sch[7] = w = word_in(in_key + 28);
+ ks8(0); ks8(1); ks8(2); ks8(3);
+ ks8(4); ks8(5); ks8(6);
+ cx->n_rnd = 14; break;
+ default:cx->n_rnd = 0; return aes_bad;
+ }
+#else
+ cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6;
+ {
+ uint32_t l = (nc * (cx->n_rnd + 1) - 1) / (klen >> 2);
+ switch(klen >> 2)
+ {
+ case 4: for(i = 0; i < l; ++i)
+ ks4(i);
+ break;
+ case 5: cx->k_sch[4] = t = word_in(in_key + 16);
+ for(i = 0; i < l; ++i)
+ ks5(i);
+ break;
+ case 6: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ for(i = 0; i < l; ++i)
+ ks6(i);
+ break;
+ case 7: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ cx->k_sch[6] = v = word_in(in_key + 24);
+ for(i = 0; i < l; ++i)
+ ks7(i);
+ break;
+ case 8: cx->k_sch[4] = t = word_in(in_key + 16);
+ cx->k_sch[5] = u = word_in(in_key + 20);
+ cx->k_sch[6] = v = word_in(in_key + 24);
+ cx->k_sch[7] = w = word_in(in_key + 28);
+ for(i = 0; i < l; ++i)
+ ks8(i);
+ break;
+ }
+ }
+#endif
+
+#if (DEC_ROUND != NO_TABLES)
+ for(i = nc; i < nc * cx->n_rnd; ++i)
+ cx->k_sch[i] = inv_mcol(cx->k_sch[i]);
+#endif
+
+ return aes_good;
+}
+
+#endif
diff --git a/src/lib/crypto/builtin/aes/aesopt.h b/src/lib/crypto/builtin/aes/aesopt.h
new file mode 100644
index 0000000..006fbb3
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aesopt.h
@@ -0,0 +1,851 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+ 1. distributions of this source code include the above copyright
+ notice, this list of conditions and the following disclaimer;
+
+ 2. distributions in binary form include the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other associated materials;
+
+ 3. the copyright holder's name is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 07/02/2002
+
+ This file contains the compilation options for AES (Rijndael) and code
+ that is common across encryption, key scheduling and table generation.
+
+
+ OPERATION
+
+ These source code files implement the AES algorithm Rijndael designed by
+ Joan Daemen and Vincent Rijmen. The version in aes.c is designed for
+ block and key sizes of 128, 192 and 256 bits (16, 24 and 32 bytes) while
+ that in aespp.c provides for block and keys sizes of 128, 160, 192, 224
+ and 256 bits (16, 20, 24, 28 and 32 bytes). This file is a common header
+ file for these two implementations and for aesref.c, which is a reference
+ implementation.
+
+ This version is designed for flexibility and speed using operations on
+ 32-bit words rather than operations on bytes. It provides aes_both fixed
+ and dynamic block and key lengths and can also run with either big or
+ little endian internal byte order (see aes.h). It inputs block and key
+ lengths in bytes with the legal values being 16, 24 and 32 for aes.c and
+ 16, 20, 24, 28 and 32 for aespp.c
+
+ THE CIPHER INTERFACE
+
+ uint8_t (an unsigned 8-bit type)
+ uint32_t (an unsigned 32-bit type)
+ aes_fret (a signed 16 bit type for function return values)
+ aes_good (value != 0, a good return)
+ aes_bad (value == 0, an error return)
+ struct aes_ctx (structure for the cipher encryption context)
+ struct aes_ctx (structure for the cipher decryption context)
+ aes_rval the function return type (aes_fret if not DLL)
+
+ C subroutine calls:
+
+ aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]);
+ aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);
+ aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+
+ aes_rval aes_dec_len(unsigned int blen, aes_ctx cx[1]);
+ aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);
+ aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);
+
+ IMPORTANT NOTE: If you are using this C interface and your compiler does
+ not set the memory used for objects to zero before use, you will need to
+ ensure that cx.s_flg is set to zero before using these subroutine calls.
+
+ C++ aes class subroutines:
+
+ class AESclass for encryption
+ class AESclass for decryption
+
+ aes_rval len(unsigned int blen = 16);
+ aes_rval key(const unsigned char in_key[], unsigned int klen);
+ aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]);
+
+ aes_rval len(unsigned int blen = 16);
+ aes_rval key(const unsigned char in_key[], unsigned int klen);
+ aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]);
+
+ The block length inputs to set_block and set_key are in numbers of
+ BYTES, not bits. The calls to subroutines must be made in the above
+ order but multiple calls can be made without repeating earlier calls
+ if their parameters have not changed. If the cipher block length is
+ variable but set_blk has not been called before cipher operations a
+ value of 16 is assumed (that is, the AES block size). In contrast to
+ earlier versions the block and key length parameters are now checked
+ for correctness and the encryption and decryption routines check to
+ ensure that an appropriate key has been set before they are called.
+
+ COMPILATION
+
+ The files used to provide AES (Rijndael) are
+
+ a. aes.h for the definitions needed for use in C.
+ b. aescpp.h for the definitions needed for use in C++.
+ c. aesopt.h for setting compilation options (also includes common
+ code).
+ d. aescrypt.c for encryption and decrytpion, or
+ e. aescrypt.asm for encryption and decryption using assembler code.
+ f. aeskey.c for key scheduling.
+ g. aestab.c for table loading or generation.
+ h. uitypes.h for defining fixed length unsigned integers.
+
+ The assembler code uses the NASM assembler. The above files provice
+ block and key lengths of 16, 24 and 32 bytes (128, 192 and 256 bits).
+ If aescrypp.c and aeskeypp.c are used instead of aescrypt.c and
+ aeskey.c respectively, the block and key lengths can then be 16, 20,
+ 24, 28 or 32 bytes. However this code has not been optimised to the
+ same extent and is hence slower (esepcially for the AES block size
+ of 16 bytes).
+
+ To compile AES (Rijndael) for use in C code use aes.h and exclude
+ the AES_DLL define in aes.h
+
+ To compile AES (Rijndael) for use in in C++ code use aescpp.h and
+ exclude the AES_DLL define in aes.h
+
+ To compile AES (Rijndael) in C as a Dynamic Link Library DLL) use
+ aes.h, include the AES_DLL define and compile the DLL. If using
+ the test files to test the DLL, exclude aes.c from the test build
+ project and compile it with the same defines as used for the DLL
+ (ensure that the DLL path is correct)
+
+ CONFIGURATION OPTIONS (here and in aes.h)
+
+ a. define BLOCK_SIZE in aes.h to set the cipher block size (16, 24
+ or 32 for the standard code, or 16, 20, 24, 28 or 32 for the
+ extended code) or leave this undefined for dynamically variable
+ block size (this will result in much slower code).
+ b. set AES_DLL in aes.h if AES (Rijndael) is to be compiled as a DLL
+ c. You may need to set PLATFORM_BYTE_ORDER to define the byte order.
+ d. If you want the code to run in a specific internal byte order, then
+ INTERNAL_BYTE_ORDER must be set accordingly.
+ e. set other configuration options decribed below.
+*/
+
+#ifndef _AESOPT_H
+#define _AESOPT_H
+
+/* START OF CONFIGURATION OPTIONS
+
+ USE OF DEFINES
+
+ Later in this section there are a number of defines that control
+ the operation of the code. In each section, the purpose of each
+ define is explained so that the relevant form can be included or
+ excluded by setting either 1's or 0's respectively on the branches
+ of the related #if clauses.
+*/
+
+#include "autoconf.h"
+
+/* 1. PLATFORM SPECIFIC INCLUDES */
+
+#if /* defined(__GNUC__) || */ defined(__GNU_LIBRARY__)
+# include <endian.h>
+# include <byteswap.h>
+#elif defined(__CRYPTLIB__)
+# if defined( INC_ALL )
+# include "crypt.h"
+# elif defined( INC_CHILD )
+# include "../crypt.h"
+# else
+# include "crypt.h"
+# endif
+# if defined(DATA_LITTLEENDIAN)
+# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+# else
+# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+# endif
+#elif defined(_MSC_VER)
+# include <stdlib.h>
+#elif defined(__m68k__) && defined(__palmos__)
+# include <FloatMgr.h> /* defines BIG_ENDIAN */
+#elif defined(_MIPSEB)
+# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+#elif defined(_MIPSEL)
+# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#elif defined(_WIN32)
+# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#elif !defined(_WIN32)
+# include <stdlib.h>
+# if defined(HAVE_ENDIAN_H)
+# include <endian.h>
+# elif defined(HAVE_MACHINE_ENDIAN_H)
+# include <machine/endian.h>
+# else
+# include <sys/param.h>
+# endif
+#endif
+
+/* 2. BYTE ORDER IN 32-BIT WORDS
+
+ To obtain the highest speed on processors with 32-bit words, this code
+ needs to determine the order in which bytes are packed into such words.
+ The following block of code is an attempt to capture the most obvious
+ ways in which various environemnts specify heir endian definitions. It
+ may well fail, in which case the definitions will need to be set by
+ editing at the points marked **** EDIT HERE IF NECESSARY **** below.
+*/
+#define AES_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
+#define AES_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
+
+#if !defined(PLATFORM_BYTE_ORDER)
+#if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN)
+# if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
+# if defined(BYTE_ORDER)
+# if (BYTE_ORDER == LITTLE_ENDIAN)
+# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+# elif (BYTE_ORDER == BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+# endif
+# endif
+# elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+# elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+# endif
+#elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN)
+# if defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
+# if defined(_BYTE_ORDER)
+# if (_BYTE_ORDER == _LITTLE_ENDIAN)
+# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+# elif (_BYTE_ORDER == _BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+# endif
+# endif
+# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+# elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
+# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+# endif
+#elif 0 /* **** EDIT HERE IF NECESSARY **** */
+#define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#elif 0 /* **** EDIT HERE IF NECESSARY **** */
+#define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN
+#elif 1
+#define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN
+#define UNKNOWN_BYTE_ORDER /* we're guessing */
+#endif
+#endif
+
+/* 3. ASSEMBLER SUPPORT
+
+ If the assembler code is used for encryption and decryption this file only
+ provides key scheduling so the following defines are used
+*/
+#ifdef AES_ASM
+#define ENCRYPTION_KEY_SCHEDULE
+#define DECRYPTION_KEY_SCHEDULE
+#endif
+
+/* 4. FUNCTIONS REQUIRED
+
+ This implementation provides five main subroutines which provide for
+ setting block length, setting encryption and decryption keys and for
+ encryption and decryption. When the assembler code is not being used
+ the following definition blocks allow the selection of the routines
+ that are to be included in the compilation.
+*/
+#if 1
+#ifndef AES_ASM
+#define SET_BLOCK_LENGTH
+#endif
+#endif
+
+#if 1
+#ifndef AES_ASM
+#define ENCRYPTION_KEY_SCHEDULE
+#endif
+#endif
+
+#if 1
+#ifndef AES_ASM
+#define DECRYPTION_KEY_SCHEDULE
+#endif
+#endif
+
+#if 1
+#ifndef AES_ASM
+#define ENCRYPTION
+#endif
+#endif
+
+#if 1
+#ifndef AES_ASM
+#define DECRYPTION
+#endif
+#endif
+
+/* 5. BYTE ORDER WITHIN 32 BIT WORDS
+
+ The fundamental data processing units in Rijndael are 8-bit bytes. The
+ input, output and key input are all enumerated arrays of bytes in which
+ bytes are numbered starting at zero and increasing to one less than the
+ number of bytes in the array in question. This enumeration is only used
+ for naming bytes and does not imply any adjacency or order relationship
+ from one byte to another. When these inputs and outputs are considered
+ as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to
+ byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte.
+ In this implementation bits are numbered from 0 to 7 starting at the
+ numerically least significant end of each byte (bit n represents 2^n).
+
+ However, Rijndael can be implemented more efficiently using 32-bit
+ words by packing bytes into words so that bytes 4*n to 4*n+3 are placed
+ into word[n]. While in principle these bytes can be assembled into words
+ in any positions, this implementation only supports the two formats in
+ which bytes in adjacent positions within words also have adjacent byte
+ numbers. This order is called big-endian if the lowest numbered bytes
+ in words have the highest numeric significance and little-endian if the
+ opposite applies.
+
+ This code can work in either order irrespective of the order used by the
+ machine on which it runs. Normally the internal byte order will be set
+ to the order of the processor on which the code is to be run but this
+ define can be used to reverse this in special situations
+*/
+#if 1
+#define INTERNAL_BYTE_ORDER PLATFORM_BYTE_ORDER
+#elif defined(AES_LITTLE_ENDIAN)
+#define INTERNAL_BYTE_ORDER AES_LITTLE_ENDIAN
+#elif defined(AES_BIG_ENDIAN)
+#define INTERNAL_BYTE_ORDER AES_BIG_ENDIAN
+#endif
+
+/* 6. FAST INPUT/OUTPUT OPERATIONS.
+
+ On some machines it is possible to improve speed by transferring the
+ bytes in the input and output arrays to and from the internal 32-bit
+ variables by addressing these arrays as if they are arrays of 32-bit
+ words. On some machines this will always be possible but there may
+ be a large performance penalty if the byte arrays are not aligned on
+ the normal word boundaries. On other machines this technique will
+ lead to memory access errors when such 32-bit word accesses are not
+ properly aligned. The option SAFE_IO avoids such problems but will
+ often be slower on those machines that support misaligned access
+ (especially so if care is taken to align the input and output byte
+ arrays on 32-bit word boundaries). If SAFE_IO is not defined it is
+ assumed that access to byte arrays as if they are arrays of 32-bit
+ words will not cause problems when such accesses are misaligned.
+*/
+#if 1
+#define SAFE_IO
+#endif
+
+/*
+ * If PLATFORM_BYTE_ORDER does not match the actual machine byte
+ * order, the fast word-access code will cause incorrect results.
+ * Therefore, SAFE_IO is required when the byte order is unknown.
+ */
+#if !defined(SAFE_IO) && defined(UNKNOWN_BYTE_ORDER)
+# error "SAFE_IO must be defined if machine byte order is unknown."
+#endif
+
+/* 7. LOOP UNROLLING
+
+ The code for encryption and decrytpion cycles through a number of rounds
+ that can be implemented either in a loop or by expanding the code into a
+ long sequence of instructions, the latter producing a larger program but
+ one that will often be much faster. The latter is called loop unrolling.
+ There are also potential speed advantages in expanding two iterations in
+ a loop with half the number of iterations, which is called partial loop
+ unrolling. The following options allow partial or full loop unrolling
+ to be set independently for encryption and decryption
+*/
+#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO)
+#define ENC_UNROLL FULL
+#elif 0
+#define ENC_UNROLL PARTIAL
+#else
+#define ENC_UNROLL NONE
+#endif
+
+#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO)
+#define DEC_UNROLL FULL
+#elif 0
+#define DEC_UNROLL PARTIAL
+#else
+#define DEC_UNROLL NONE
+#endif
+
+/* 8. FIXED OR DYNAMIC TABLES
+
+ When this section is included the tables used by the code are compiled
+ statically into the binary file. Otherwise they are computed once when
+ the code is first used.
+*/
+#if 1
+#define FIXED_TABLES
+#endif
+
+/* 9. FAST FINITE FIELD OPERATIONS
+
+ If this section is included, tables are used to provide faster finite
+ field arithmetic (this has no effect if FIXED_TABLES is defined).
+*/
+#if 1
+#define FF_TABLES
+#endif
+
+/* 10. INTERNAL STATE VARIABLE FORMAT
+
+ The internal state of Rijndael is stored in a number of local 32-bit
+ word varaibles which can be defined either as an array or as individual
+ names variables. Include this section if you want to store these local
+ varaibles in arrays. Otherwise individual local variables will be used.
+*/
+#if 1
+#define ARRAYS
+#endif
+
+/* In this implementation the columns of the state array are each held in
+ 32-bit words. The state array can be held in various ways: in an array
+ of words, in a number of individual word variables or in a number of
+ processor registers. The following define maps a variable name x and
+ a column number c to the way the state array variable is to be held.
+ The first define below maps the state into an array x[c] whereas the
+ second form maps the state into a number of individual variables x0,
+ x1, etc. Another form could map individual state colums to machine
+ register names.
+*/
+
+#if defined(ARRAYS)
+#define s(x,c) x[c]
+#else
+#define s(x,c) x##c
+#endif
+
+/* 11. VARIABLE BLOCK SIZE SPEED
+
+ This section is only relevant if you wish to use the variable block
+ length feature of the code. Include this section if you place more
+ emphasis on speed rather than code size.
+*/
+#if 1
+#define FAST_VARIABLE
+#endif
+
+/* 12. INTERNAL TABLE CONFIGURATION
+
+ This cipher proceeds by repeating in a number of cycles known as 'rounds'
+ which are implemented by a round function which can optionally be speeded
+ up using tables. The basic tables are each 256 32-bit words, with either
+ one or four tables being required for each round function depending on
+ how much speed is required. The encryption and decryption round functions
+ are different and the last encryption and decrytpion round functions are
+ different again making four different round functions in all.
+
+ This means that:
+ 1. Normal encryption and decryption rounds can each use either 0, 1
+ or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
+ 2. The last encryption and decryption rounds can also use either 0, 1
+ or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
+
+ Include or exclude the appropriate definitions below to set the number
+ of tables used by this implementation.
+*/
+
+#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the normal encryption round */
+#define ENC_ROUND FOUR_TABLES
+#elif 0
+#define ENC_ROUND ONE_TABLE
+#else
+#define ENC_ROUND NO_TABLES
+#endif
+
+#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the last encryption round */
+#define LAST_ENC_ROUND FOUR_TABLES
+#elif 0
+#define LAST_ENC_ROUND ONE_TABLE
+#else
+#define LAST_ENC_ROUND NO_TABLES
+#endif
+
+#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the normal decryption round */
+#define DEC_ROUND FOUR_TABLES
+#elif 0
+#define DEC_ROUND ONE_TABLE
+#else
+#define DEC_ROUND NO_TABLES
+#endif
+
+#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the last decryption round */
+#define LAST_DEC_ROUND FOUR_TABLES
+#elif 0
+#define LAST_DEC_ROUND ONE_TABLE
+#else
+#define LAST_DEC_ROUND NO_TABLES
+#endif
+
+/* The decryption key schedule can be speeded up with tables in the same
+ way that the round functions can. Include or exclude the following
+ defines to set this requirement.
+*/
+#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO)
+#define KEY_SCHED FOUR_TABLES
+#elif 0
+#define KEY_SCHED ONE_TABLE
+#else
+#define KEY_SCHED NO_TABLES
+#endif
+
+/* END OF CONFIGURATION OPTIONS */
+
+#define NO_TABLES 0 /* DO NOT CHANGE */
+#define ONE_TABLE 1 /* DO NOT CHANGE */
+#define FOUR_TABLES 4 /* DO NOT CHANGE */
+#define NONE 0 /* DO NOT CHANGE */
+#define PARTIAL 1 /* DO NOT CHANGE */
+#define FULL 2 /* DO NOT CHANGE */
+
+#if defined(BLOCK_SIZE) && ((BLOCK_SIZE & 3) || BLOCK_SIZE < 16 || BLOCK_SIZE > 32)
+#error An illegal block size has been specified.
+#endif
+
+#if !defined(BLOCK_SIZE)
+#define RC_LENGTH 29
+#else
+#define RC_LENGTH 5 * BLOCK_SIZE / 4 - (BLOCK_SIZE == 16 ? 10 : 11)
+#endif
+
+/* Disable at least some poor combinations of options */
+
+#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES
+#undef LAST_ENC_ROUND
+#define LAST_ENC_ROUND NO_TABLES
+#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES
+#undef LAST_ENC_ROUND
+#define LAST_ENC_ROUND ONE_TABLE
+#endif
+
+#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE
+#undef ENC_UNROLL
+#define ENC_UNROLL NONE
+#endif
+
+#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES
+#undef LAST_DEC_ROUND
+#define LAST_DEC_ROUND NO_TABLES
+#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES
+#undef LAST_DEC_ROUND
+#define LAST_DEC_ROUND ONE_TABLE
+#endif
+
+#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE
+#undef DEC_UNROLL
+#define DEC_UNROLL NONE
+#endif
+
+#include "aes.h"
+
+ /*
+ upr(x,n): rotates bytes within words by n positions, moving bytes to
+ higher index positions with wrap around into low positions
+ ups(x,n): moves bytes by n positions to higher index positions in
+ words but without wrap around
+ bval(x,n): extracts a byte from a word
+ */
+
+#if (INTERNAL_BYTE_ORDER == AES_LITTLE_ENDIAN)
+#if defined(_MSC_VER)
+#define upr(x,n) _lrotl((x), 8 * (n))
+#else
+#define upr(x,n) (((x) << (8 * (n))) | ((x) >> (32 - 8 * (n))))
+#endif
+#define ups(x,n) ((x) << (8 * (n)))
+#define bval(x,n) ((uint8_t)((x) >> (8 * (n))))
+#define bytes2word(b0, b1, b2, b3) \
+ (((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0))
+#endif
+
+#if (INTERNAL_BYTE_ORDER == AES_BIG_ENDIAN)
+#define upr(x,n) (((x) >> (8 * (n))) | ((x) << (32 - 8 * (n))))
+#define ups(x,n) ((x) >> (8 * (n))))
+#define bval(x,n) ((uint8_t)((x) >> (24 - 8 * (n))))
+#define bytes2word(b0, b1, b2, b3) \
+ (((uint32_t)(b0) << 24) | ((uint32_t)(b1) << 16) | ((uint32_t)(b2) << 8) | (b3))
+#endif
+
+#if defined(SAFE_IO)
+
+#define word_in(x) bytes2word((x)[0], (x)[1], (x)[2], (x)[3])
+#define word_out(x,v) { (x)[0] = bval(v,0); (x)[1] = bval(v,1); \
+ (x)[2] = bval(v,2); (x)[3] = bval(v,3); }
+
+#elif (INTERNAL_BYTE_ORDER == PLATFORM_BYTE_ORDER)
+
+#define word_in(x) *(uint32_t*)(x)
+#define word_out(x,v) *(uint32_t*)(x) = (v)
+
+#else
+
+#if !defined(bswap_32)
+#if !defined(_MSC_VER)
+#define _lrotl(x,n) (((x) << n) | ((x) >> (32 - n)))
+#endif
+#define bswap_32(x) ((_lrotl((x),8) & 0x00ff00ff) | (_lrotl((x),24) & 0xff00ff00))
+#endif
+
+#define word_in(x) bswap_32(*(uint32_t*)(x))
+#define word_out(x,v) *(uint32_t*)(x) = bswap_32(v)
+
+#endif
+
+/* the finite field modular polynomial and elements */
+
+#define WPOLY 0x011b
+#define BPOLY 0x1b
+
+/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+#define m1 0x80808080
+#define m2 0x7f7f7f7f
+#define FFmulX(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY))
+
+/* The following defines provide alternative definitions of FFmulX that might
+ give improved performance if a fast 32-bit multiply is not available. Note
+ that a temporary variable u needs to be defined where FFmulX is used.
+
+#define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6))
+#define m4 (0x01010101 * BPOLY)
+#define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4)
+*/
+
+/* Work out which tables are needed for the different options */
+
+#ifdef AES_ASM
+#ifdef ENC_ROUND
+#undef ENC_ROUND
+#endif
+#define ENC_ROUND FOUR_TABLES
+#ifdef LAST_ENC_ROUND
+#undef LAST_ENC_ROUND
+#endif
+#define LAST_ENC_ROUND FOUR_TABLES
+#ifdef DEC_ROUND
+#undef DEC_ROUND
+#endif
+#define DEC_ROUND FOUR_TABLES
+#ifdef LAST_DEC_ROUND
+#undef LAST_DEC_ROUND
+#endif
+#define LAST_DEC_ROUND FOUR_TABLES
+#ifdef KEY_SCHED
+#undef KEY_SCHED
+#define KEY_SCHED FOUR_TABLES
+#endif
+#endif
+
+#if defined(ENCRYPTION) || defined(AES_ASM)
+#if ENC_ROUND == ONE_TABLE
+#define FT1_SET
+#elif ENC_ROUND == FOUR_TABLES
+#define FT4_SET
+#else
+#define SBX_SET
+#endif
+#if LAST_ENC_ROUND == ONE_TABLE
+#define FL1_SET
+#elif LAST_ENC_ROUND == FOUR_TABLES
+#define FL4_SET
+#elif !defined(SBX_SET)
+#define SBX_SET
+#endif
+#endif
+
+#if defined(DECRYPTION) || defined(AES_ASM)
+#if DEC_ROUND == ONE_TABLE
+#define IT1_SET
+#elif DEC_ROUND == FOUR_TABLES
+#define IT4_SET
+#else
+#define ISB_SET
+#endif
+#if LAST_DEC_ROUND == ONE_TABLE
+#define IL1_SET
+#elif LAST_DEC_ROUND == FOUR_TABLES
+#define IL4_SET
+#elif !defined(ISB_SET)
+#define ISB_SET
+#endif
+#endif
+
+#if defined(ENCRYPTION_KEY_SCHEDULE) || defined(DECRYPTION_KEY_SCHEDULE)
+#if KEY_SCHED == ONE_TABLE
+#define LS1_SET
+#define IM1_SET
+#elif KEY_SCHED == FOUR_TABLES
+#define LS4_SET
+#define IM4_SET
+#elif !defined(SBX_SET)
+#define SBX_SET
+#endif
+#endif
+
+#ifdef FIXED_TABLES
+#define prefx extern const
+#else
+#define prefx extern
+extern uint8_t tab_init;
+void gen_tabs(void);
+#endif
+
+prefx uint32_t rcon_tab[29];
+
+#ifdef SBX_SET
+prefx uint8_t s_box[256];
+#endif
+
+#ifdef ISB_SET
+prefx uint8_t inv_s_box[256];
+#endif
+
+#ifdef FT1_SET
+prefx uint32_t ft_tab[256];
+#endif
+
+#ifdef FT4_SET
+prefx uint32_t ft_tab[4][256];
+#endif
+
+#ifdef FL1_SET
+prefx uint32_t fl_tab[256];
+#endif
+
+#ifdef FL4_SET
+prefx uint32_t fl_tab[4][256];
+#endif
+
+#ifdef IT1_SET
+prefx uint32_t it_tab[256];
+#endif
+
+#ifdef IT4_SET
+prefx uint32_t it_tab[4][256];
+#endif
+
+#ifdef IL1_SET
+prefx uint32_t il_tab[256];
+#endif
+
+#ifdef IL4_SET
+prefx uint32_t il_tab[4][256];
+#endif
+
+#ifdef LS1_SET
+#ifdef FL1_SET
+#undef LS1_SET
+#else
+prefx uint32_t ls_tab[256];
+#endif
+#endif
+
+#ifdef LS4_SET
+#ifdef FL4_SET
+#undef LS4_SET
+#else
+prefx uint32_t ls_tab[4][256];
+#endif
+#endif
+
+#ifdef IM1_SET
+prefx uint32_t im_tab[256];
+#endif
+
+#ifdef IM4_SET
+prefx uint32_t im_tab[4][256];
+#endif
+
+/* Set the number of columns in nc. Note that it is important */
+/* that nc is a constant which is known at compile time if the */
+/* highest speed version of the code is needed */
+
+#if defined(BLOCK_SIZE)
+#define nc (BLOCK_SIZE >> 2)
+#else
+#define nc (cx->n_blk >> 2)
+#endif
+
+/* generic definitions of Rijndael macros that use of tables */
+
+#define no_table(x,box,vf,rf,c) bytes2word( \
+ box[bval(vf(x,0,c),rf(0,c))], \
+ box[bval(vf(x,1,c),rf(1,c))], \
+ box[bval(vf(x,2,c),rf(2,c))], \
+ box[bval(vf(x,3,c),rf(3,c))])
+
+#define one_table(x,op,tab,vf,rf,c) \
+ ( tab[bval(vf(x,0,c),rf(0,c))] \
+ ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \
+ ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \
+ ^ op(tab[bval(vf(x,3,c),rf(3,c))],3))
+
+#define four_tables(x,tab,vf,rf,c) \
+ ( tab[0][bval(vf(x,0,c),rf(0,c))] \
+ ^ tab[1][bval(vf(x,1,c),rf(1,c))] \
+ ^ tab[2][bval(vf(x,2,c),rf(2,c))] \
+ ^ tab[3][bval(vf(x,3,c),rf(3,c))])
+
+#define vf1(x,r,c) (x)
+#define rf1(r,c) (r)
+#define rf2(r,c) ((r-c)&3)
+
+/* perform forward and inverse column mix operation on four bytes in long word x in */
+/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */
+
+#define dec_fmvars
+#if defined(FM4_SET) /* not currently used */
+#define fwd_mcol(x) four_tables(x,fm_tab,vf1,rf1,0)
+#elif defined(FM1_SET) /* not currently used */
+#define fwd_mcol(x) one_table(x,upr,fm_tab,vf1,rf1,0)
+#else
+#undef dec_fmvars
+#define dec_fmvars uint32_t f1, f2;
+#define fwd_mcol(x) (f1 = (x), f2 = FFmulX(f1), f2 ^ upr(f1 ^ f2, 3) ^ upr(f1, 2) ^ upr(f1, 1))
+#endif
+
+#define dec_imvars
+#if defined(IM4_SET)
+#define inv_mcol(x) four_tables(x,im_tab,vf1,rf1,0)
+#elif defined(IM1_SET)
+#define inv_mcol(x) one_table(x,upr,im_tab,vf1,rf1,0)
+#else
+#undef dec_imvars
+#define dec_imvars uint32_t f2, f4, f8, f9;
+#define inv_mcol(x) \
+ (f9 = (x), f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \
+ f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1))
+#endif
+
+#if defined(FL4_SET)
+#define ls_box(x,c) four_tables(x,fl_tab,vf1,rf2,c)
+#elif defined(LS4_SET)
+#define ls_box(x,c) four_tables(x,ls_tab,vf1,rf2,c)
+#elif defined(FL1_SET)
+#define ls_box(x,c) one_table(x,upr,fl_tab,vf1,rf2,c)
+#elif defined(LS1_SET)
+#define ls_box(x,c) one_table(x,upr,ls_tab,vf1,rf2,c)
+#else
+#define ls_box(x,c) no_table(x,s_box,vf1,rf2,c)
+#endif
+
+#endif
diff --git a/src/lib/crypto/builtin/aes/aessrc.url b/src/lib/crypto/builtin/aes/aessrc.url
new file mode 100644
index 0000000..0758737
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aessrc.url
@@ -0,0 +1 @@
+http://fp.gladman.plus.com/cryptography_technology/rijndael/index.htm
diff --git a/src/lib/crypto/builtin/aes/aestab.c b/src/lib/crypto/builtin/aes/aestab.c
new file mode 100644
index 0000000..7a5d69f
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/aestab.c
@@ -0,0 +1,494 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+ 1. distributions of this source code include the above copyright
+ notice, this list of conditions and the following disclaimer;
+
+ 2. distributions in binary form include the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other associated materials;
+
+ 3. the copyright holder's name is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 07/02/2002
+*/
+
+#include "aesopt.h"
+
+#if defined(FIXED_TABLES) || !defined(FF_TABLES)
+
+/* finite field arithmetic operations */
+
+#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY))
+#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY))
+#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \
+ ^ (((x>>5) & 4) * WPOLY))
+#define f3(x) (f2(x) ^ x)
+#define f9(x) (f8(x) ^ x)
+#define fb(x) (f8(x) ^ f2(x) ^ x)
+#define fd(x) (f8(x) ^ f4(x) ^ x)
+#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
+
+#endif
+
+#if defined(FIXED_TABLES)
+
+#define sb_data(w) \
+ w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
+ w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
+ w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
+ w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
+ w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
+ w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
+ w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
+ w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
+ w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
+ w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
+ w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
+ w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
+ w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
+ w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
+ w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
+ w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
+ w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
+ w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
+ w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
+ w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
+ w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
+ w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
+ w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
+ w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
+ w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
+ w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
+ w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
+ w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
+ w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
+ w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
+ w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
+ w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16)
+
+#define isb_data(w) \
+ w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
+ w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
+ w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
+ w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
+ w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
+ w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
+ w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
+ w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
+ w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
+ w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
+ w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
+ w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
+ w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
+ w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
+ w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
+ w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
+ w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
+ w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
+ w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
+ w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
+ w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
+ w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
+ w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
+ w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
+ w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
+ w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
+ w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
+ w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
+ w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
+ w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
+ w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
+ w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d),
+
+#define mm_data(w) \
+ w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
+ w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
+ w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
+ w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
+ w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
+ w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
+ w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
+ w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
+ w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
+ w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
+ w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
+ w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
+ w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
+ w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
+ w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
+ w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
+ w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
+ w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
+ w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
+ w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
+ w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
+ w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
+ w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
+ w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
+ w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
+ w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
+ w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
+ w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
+ w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
+ w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
+ w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
+ w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff)
+
+#define h0(x) (x)
+
+/* These defines are used to ensure tables are generated in the
+ right format depending on the internal byte order required
+*/
+
+#define w0(p) bytes2word(p, 0, 0, 0)
+#define w1(p) bytes2word(0, p, 0, 0)
+#define w2(p) bytes2word(0, 0, p, 0)
+#define w3(p) bytes2word(0, 0, 0, p)
+
+/* Number of elements required in this table for different
+ block and key lengths is:
+
+ Rcon Table key length (bytes)
+ Length 16 20 24 28 32
+ ---------------------
+ block 16 | 10 9 8 7 7
+ length 20 | 14 11 10 9 9
+ (bytes) 24 | 19 15 12 11 11
+ 28 | 24 19 16 13 13
+ 32 | 29 23 19 17 14
+
+ this table can be a table of bytes if the key schedule
+ code is adjusted accordingly
+*/
+
+#define u0(p) bytes2word(f2(p), p, p, f3(p))
+#define u1(p) bytes2word(f3(p), f2(p), p, p)
+#define u2(p) bytes2word(p, f3(p), f2(p), p)
+#define u3(p) bytes2word(p, p, f3(p), f2(p))
+
+#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p))
+#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p))
+#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p))
+#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p))
+
+const uint32_t rcon_tab[29] =
+{
+ w0(0x01), w0(0x02), w0(0x04), w0(0x08),
+ w0(0x10), w0(0x20), w0(0x40), w0(0x80),
+ w0(0x1b), w0(0x36), w0(0x6c), w0(0xd8),
+ w0(0xab), w0(0x4d), w0(0x9a), w0(0x2f),
+ w0(0x5e), w0(0xbc), w0(0x63), w0(0xc6),
+ w0(0x97), w0(0x35), w0(0x6a), w0(0xd4),
+ w0(0xb3), w0(0x7d), w0(0xfa), w0(0xef),
+ w0(0xc5)
+};
+
+#ifdef SBX_SET
+const uint8_t s_box[256] = { sb_data(h0) };
+#endif
+#ifdef ISB_SET
+const uint8_t inv_s_box[256] = { isb_data(h0) };
+#endif
+
+#ifdef FT1_SET
+const uint32_t ft_tab[256] = { sb_data(u0) };
+#endif
+#ifdef FT4_SET
+const uint32_t ft_tab[4][256] =
+ { { sb_data(u0) }, { sb_data(u1) }, { sb_data(u2) }, { sb_data(u3) } };
+#endif
+
+#ifdef FL1_SET
+const uint32_t fl_tab[256] = { sb_data(w0) };
+#endif
+#ifdef FL4_SET
+const uint32_t fl_tab[4][256] =
+ { { sb_data(w0) }, { sb_data(w1) }, { sb_data(w2) }, { sb_data(w3) } };
+#endif
+
+#ifdef IT1_SET
+const uint32_t it_tab[256] = { isb_data(v0) };
+#endif
+#ifdef IT4_SET
+const uint32_t it_tab[4][256] =
+ { { isb_data(v0) }, { isb_data(v1) }, { isb_data(v2) }, { isb_data(v3) } };
+#endif
+
+#ifdef IL1_SET
+const uint32_t il_tab[256] = { isb_data(w0) };
+#endif
+#ifdef IL4_SET
+const uint32_t il_tab[4][256] =
+ { { isb_data(w0) }, { isb_data(w1) }, { isb_data(w2) }, { isb_data(w3) } };
+#endif
+
+#ifdef LS1_SET
+const uint32_t ls_tab[256] = { sb_data(w0) };
+#endif
+#ifdef LS4_SET
+const uint32_t ls_tab[4][256] =
+ { { sb_data(w0) }, { sb_data(w1) }, { sb_data(w2) }, { sb_data(w3) } };
+#endif
+
+#ifdef IM1_SET
+const uint32_t im_tab[256] = { mm_data(v0) };
+#endif
+#ifdef IM4_SET
+const uint32_t im_tab[4][256] =
+ { { mm_data(v0) }, { mm_data(v1) }, { mm_data(v2) }, { mm_data(v3) } };
+#endif
+
+#else /* dynamic table generation */
+
+uint8_t tab_init = 0;
+
+#define const
+
+uint32_t rcon_tab[RC_LENGTH];
+
+#ifdef SBX_SET
+uint8_t s_box[256];
+#endif
+#ifdef ISB_SET
+uint8_t inv_s_box[256];
+#endif
+
+#ifdef FT1_SET
+uint32_t ft_tab[256];
+#endif
+#ifdef FT4_SET
+uint32_t ft_tab[4][256];
+#endif
+
+#ifdef FL1_SET
+uint32_t fl_tab[256];
+#endif
+#ifdef FL4_SET
+uint32_t fl_tab[4][256];
+#endif
+
+#ifdef IT1_SET
+uint32_t it_tab[256];
+#endif
+#ifdef IT4_SET
+uint32_t it_tab[4][256];
+#endif
+
+#ifdef IL1_SET
+uint32_t il_tab[256];
+#endif
+#ifdef IL4_SET
+uint32_t il_tab[4][256];
+#endif
+
+#ifdef LS1_SET
+uint32_t ls_tab[256];
+#endif
+#ifdef LS4_SET
+uint32_t ls_tab[4][256];
+#endif
+
+#ifdef IM1_SET
+uint32_t im_tab[256];
+#endif
+#ifdef IM4_SET
+uint32_t im_tab[4][256];
+#endif
+
+#if !defined(FF_TABLES)
+
+/* Generate the tables for the dynamic table option
+
+ It will generally be sensible to use tables to compute finite
+ field multiplies and inverses but where memory is scarse this
+ code might sometimes be better. But it only has effect during
+ initialisation so its pretty unimportant in overall terms.
+*/
+
+/* return 2 ^ (n - 1) where n is the bit number of the highest bit
+ set in x with x in the range 1 < x < 0x00000200. This form is
+ used so that locals within fi can be bytes rather than words
+*/
+
+static uint8_t hibit(const uint32_t x)
+{ uint8_t r = (uint8_t)((x >> 1) | (x >> 2));
+
+ r |= (r >> 2);
+ r |= (r >> 4);
+ return (r + 1) >> 1;
+}
+
+/* return the inverse of the finite field element x */
+
+static uint8_t fi(const uint8_t x)
+{ uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
+
+ if(x < 2) return x;
+
+ for(;;)
+ {
+ if(!n1) return v1;
+
+ while(n2 >= n1)
+ {
+ n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2);
+ }
+
+ if(!n2) return v2;
+
+ while(n1 >= n2)
+ {
+ n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1);
+ }
+ }
+}
+
+#else
+
+/* define the finite field multiplies required for Rijndael */
+
+#define f2(x) ((x) ? pow[log[x] + 0x19] : 0)
+#define f3(x) ((x) ? pow[log[x] + 0x01] : 0)
+#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0)
+#define fb(x) ((x) ? pow[log[x] + 0x68] : 0)
+#define fd(x) ((x) ? pow[log[x] + 0xee] : 0)
+#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0)
+#define fi(x) ((x) ? pow[255 - log[x]]: 0)
+
+#endif
+
+/* The forward and inverse affine transformations used in the S-box */
+
+#define fwd_affine(x) \
+ (w = (uint32_t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(uint8_t)(w^(w>>8)))
+
+#define inv_affine(x) \
+ (w = (uint32_t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(uint8_t)(w^(w>>8)))
+
+void gen_tabs(void)
+{ uint32_t i, w;
+
+#if defined(FF_TABLES)
+
+ uint8_t pow[512], log[256];
+
+ /* log and power tables for GF(2^8) finite field with
+ WPOLY as modular polynomial - the simplest primitive
+ root is 0x03, used here to generate the tables
+ */
+
+ i = 0; w = 1;
+ do
+ {
+ pow[i] = (uint8_t)w;
+ pow[i + 255] = (uint8_t)w;
+ log[w] = (uint8_t)i++;
+ w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0);
+ }
+ while (w != 1);
+
+#endif
+
+ for(i = 0, w = 1; i < RC_LENGTH; ++i)
+ {
+ rcon_tab[i] = bytes2word(w, 0, 0, 0);
+ w = f2(w);
+ }
+
+ for(i = 0; i < 256; ++i)
+ { uint8_t b;
+
+ b = fwd_affine(fi((uint8_t)i));
+ w = bytes2word(f2(b), b, b, f3(b));
+
+#ifdef SBX_SET
+ s_box[i] = b;
+#endif
+
+#ifdef FT1_SET /* tables for a normal encryption round */
+ ft_tab[i] = w;
+#endif
+#ifdef FT4_SET
+ ft_tab[0][i] = w;
+ ft_tab[1][i] = upr(w,1);
+ ft_tab[2][i] = upr(w,2);
+ ft_tab[3][i] = upr(w,3);
+#endif
+ w = bytes2word(b, 0, 0, 0);
+
+#ifdef FL1_SET /* tables for last encryption round (may also */
+ fl_tab[i] = w; /* be used in the key schedule) */
+#endif
+#ifdef FL4_SET
+ fl_tab[0][i] = w;
+ fl_tab[1][i] = upr(w,1);
+ fl_tab[2][i] = upr(w,2);
+ fl_tab[3][i] = upr(w,3);
+#endif
+
+#ifdef LS1_SET /* table for key schedule if fl_tab above is */
+ ls_tab[i] = w; /* not of the required form */
+#endif
+#ifdef LS4_SET
+ ls_tab[0][i] = w;
+ ls_tab[1][i] = upr(w,1);
+ ls_tab[2][i] = upr(w,2);
+ ls_tab[3][i] = upr(w,3);
+#endif
+
+ b = fi(inv_affine((uint8_t)i));
+ w = bytes2word(fe(b), f9(b), fd(b), fb(b));
+
+#ifdef IM1_SET /* tables for the inverse mix column operation */
+ im_tab[b] = w;
+#endif
+#ifdef IM4_SET
+ im_tab[0][b] = w;
+ im_tab[1][b] = upr(w,1);
+ im_tab[2][b] = upr(w,2);
+ im_tab[3][b] = upr(w,3);
+#endif
+
+#ifdef ISB_SET
+ inv_s_box[i] = b;
+#endif
+#ifdef IT1_SET /* tables for a normal decryption round */
+ it_tab[i] = w;
+#endif
+#ifdef IT4_SET
+ it_tab[0][i] = w;
+ it_tab[1][i] = upr(w,1);
+ it_tab[2][i] = upr(w,2);
+ it_tab[3][i] = upr(w,3);
+#endif
+ w = bytes2word(b, 0, 0, 0);
+#ifdef IL1_SET /* tables for last decryption round */
+ il_tab[i] = w;
+#endif
+#ifdef IL4_SET
+ il_tab[0][i] = w;
+ il_tab[1][i] = upr(w,1);
+ il_tab[2][i] = upr(w,2);
+ il_tab[3][i] = upr(w,3);
+#endif
+ }
+
+ tab_init = 1;
+}
+
+#endif
diff --git a/src/lib/crypto/builtin/aes/deps b/src/lib/crypto/builtin/aes/deps
new file mode 100644
index 0000000..08ce3fa
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/deps
@@ -0,0 +1,21 @@
+#
+# Generated makefile dependencies follow.
+#
+aescrypt.so aescrypt.po $(OUTPRE)aescrypt.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h aes.h aescrypt.c aesopt.h \
+ uitypes.h
+aestab.so aestab.po $(OUTPRE)aestab.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ aes.h aesopt.h aestab.c uitypes.h
+aeskey.so aeskey.po $(OUTPRE)aeskey.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ aes.h aeskey.c aesopt.h uitypes.h
+aes_s2k.so aes_s2k.po $(OUTPRE)aes_s2k.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h \
+ $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \
+ $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
+ $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+ $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+ $(SRCTOP)/include/socket-utils.h $(srcdir)/../../krb/dk/dk.h \
+ aes_s2k.c aes_s2k.h
diff --git a/src/lib/crypto/builtin/aes/uitypes.h b/src/lib/crypto/builtin/aes/uitypes.h
new file mode 100644
index 0000000..3a72921
--- /dev/null
+++ b/src/lib/crypto/builtin/aes/uitypes.h
@@ -0,0 +1,83 @@
+/*
+ -------------------------------------------------------------------------
+ Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+ 1. distributions of this source code include the above copyright
+ notice, this list of conditions and the following disclaimer;
+
+ 2. distributions in binary form include the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other associated materials;
+
+ 3. the copyright holder's name is not used to endorse products
+ built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explcit or implied warranties
+ in respect of any properties, including, but not limited to, correctness
+ and fitness for purpose.
+ -------------------------------------------------------------------------
+ Issue Date: 01/02/2002
+
+ This file contains code to obtain or set the definitions for fixed length
+ unsigned integer types.
+*/
+
+#ifndef _UITYPES_H
+#define _UITYPES_H
+
+#include "autoconf.h"
+
+#if defined(__GNU_LIBRARY__)
+#define HAS_INTTYPES_H
+#elif !defined(_MSC_VER)
+#include <limits.h>
+#if ULONG_MAX > 0xFFFFFFFFUL
+ #define MODEL_64
+#else
+ #define MODEL_32
+#endif
+#endif
+
+#if defined HAS_INTTYPES_H || defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#define s_u32 u
+#define s_u64 ull
+#elif defined MODEL_32
+typedef unsigned char uint8_t;
+typedef unsigned short int uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long int uint64_t;
+#define s_u32 u
+#define s_u64 ull
+#elif defined MODEL_64
+typedef unsigned char uint8_t;
+typedef unsigned short int uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long int uint64_t;
+#define s_u32 u
+#define s_u64 ul
+#elif defined(_MSC_VER)
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#define s_u32 ui32
+#define s_u64 ui64
+#else
+#error You need to define fixed length types in uitypes.h
+#endif
+
+#define sfx_lo(x,y) x##y
+#define sfx_hi(x,y) sfx_lo(x,y)
+#define x_32(p) sfx_hi(0x##p,s_u32)
+#define x_64(p) sfx_hi(0x##p,s_u64)
+
+#endif