diff options
author | Cy Schubert <cy@FreeBSD.org> | 2017-07-07 17:03:42 +0000 |
---|---|---|
committer | Cy Schubert <cy@FreeBSD.org> | 2017-07-07 17:03:42 +0000 |
commit | 33a9b234e7087f573ef08cd7318c6497ba08b439 (patch) | |
tree | d0ea40ad3bf5463a3c55795977c71bcb7d781b4b /src/lib/crypto | |
download | src-33a9b234e7087f573ef08cd7318c6497ba08b439.tar.gz src-33a9b234e7087f573ef08cd7318c6497ba08b439.zip |
Import MIT KRB5 1.15.1, which will gracefully replace KTH Heimdal.vendor/krb5/1.15.1
The tarball used in this import is the same tarball used in
ports/krb5-115 r435378.
Obtained from: http://web.mit.edu/kerberos/dist/
Thanks to: pfg (for all your tireless behind-the-scenes effort)
Notes
Notes:
svn path=/vendor-crypto/krb5/dist/; revision=320790
svn path=/vendor-crypto/krb5/1.15.1/; revision=320791; tag=vendor/krb5/1.15.1
Diffstat (limited to 'src/lib/crypto')
242 files changed, 71816 insertions, 0 deletions
diff --git a/src/lib/crypto/ISSUES b/src/lib/crypto/ISSUES new file mode 100644 index 000000000000..b821a00c6cc2 --- /dev/null +++ b/src/lib/crypto/ISSUES @@ -0,0 +1,14 @@ +Issues to be addressed for src/lib/crypto: -*- text -*- + + +Many files here and in subdirectories pollute the namespace. +However, some applications wanting to directly use some of those +routines will expect those names to be available. + +Workaround: Shared library export lists? Define and export internal +names, and provide wrapper library code or weak functions under the +polluting names? + + +Some routines assume "int" is big enough to describe all buffers that +may be supplied. diff --git a/src/lib/crypto/Makefile.in b/src/lib/crypto/Makefile.in new file mode 100644 index 000000000000..c3fcfd7e85fc --- /dev/null +++ b/src/lib/crypto/Makefile.in @@ -0,0 +1,54 @@ +mydir=lib$(S)crypto +BUILDTOP=$(REL)..$(S).. +SUBDIRS= krb $(CRYPTO_IMPL) crypto_tests + +LIBBASE=k5crypto +LIBMAJOR=3 +LIBMINOR=1 +LIBINITFUNC=cryptoint_initialize_library +LIBFINIFUNC=cryptoint_cleanup_library +RELDIR=crypto + +STOBJLISTS=$(CRYPTO_IMPL)/enc_provider/OBJS.ST \ + $(CRYPTO_IMPL)/hash_provider/OBJS.ST \ + $(CRYPTO_IMPL)/md4/OBJS.ST $(CRYPTO_IMPL)/md5/OBJS.ST \ + $(CRYPTO_IMPL)/sha1/OBJS.ST $(CRYPTO_IMPL)/sha2/OBJS.ST \ + $(CRYPTO_IMPL)/aes/OBJS.ST $(CRYPTO_IMPL)/des/OBJS.ST \ + $(CRYPTO_IMPL)/camellia/OBJS.ST krb/OBJS.ST \ + $(CRYPTO_IMPL)/OBJS.ST + +SUBDIROBJLISTS=$(CRYPTO_IMPL)/enc_provider/OBJS.ST \ + $(CRYPTO_IMPL)/hash_provider/OBJS.ST \ + $(CRYPTO_IMPL)/md4/OBJS.ST $(CRYPTO_IMPL)/md5/OBJS.ST \ + $(CRYPTO_IMPL)/sha1/OBJS.ST $(CRYPTO_IMPL)/sha2/OBJS.ST \ + $(CRYPTO_IMPL)/aes/OBJS.ST $(CRYPTO_IMPL)/des/OBJS.ST \ + $(CRYPTO_IMPL)/camellia/OBJS.ST krb/OBJS.ST \ + $(CRYPTO_IMPL)/OBJS.ST + +# No dependencies. Record places to find this shared object if the target +# link editor and loader support it. +DEPLIBS= +CRYPTO_IMPL_LIBS=@CRYPTO_IMPL_LIBS@ +SHLIB_EXPLIBS= $(SUPPORT_LIB) $(CRYPTO_IMPL_LIBS) $(LIBS) +SHLIB_EXPDEPLIBS= $(SUPPORT_DEPLIB) +SHLIB_LDFLAGS= $(LDFLAGS) @SHLIB_RPATH_DIRS@ + +##DOS##LIBNAME=$(OUTPRE)crypto.lib +##DOS##OBJFILEDEP=$(OUTPRE)krb.lst $(OUTPRE)aes.lst $(OUTPRE)enc_provider.lst $(OUTPRE)des.lst $(OUTPRE)md5.lst $(OUTPRE)camellia.lst $(OUTPRE)md4.lst $(OUTPRE)hash_provider.lst $(OUTPRE)sha2.lst $(OUTPRE)sha1.lst $(OUTPRE)builtin.lst +##DOS##OBJFILELIST=@$(OUTPRE)krb.lst @$(OUTPRE)aes.lst @$(OUTPRE)enc_provider.lst @$(OUTPRE)des.lst @$(OUTPRE)md5.lst @$(OUTPRE)camellia.lst @$(OUTPRE)md4.lst @$(OUTPRE)hash_provider.lst @$(OUTPRE)sha2.lst @$(OUTPRE)sha1.lst @$(OUTPRE)builtin.lst + +all-unix: all-liblinks +install-unix: install-libs + + +# all-unix: +# install-unix: + +libcrypto.lib: + libdir crypto.lib + +clean-unix:: clean-liblinks clean-libs clean-libobjs + +@lib_frag@ +@libobj_frag@ + diff --git a/src/lib/crypto/builtin/Makefile.in b/src/lib/crypto/builtin/Makefile.in new file mode 100644 index 000000000000..baf5d974f5b4 --- /dev/null +++ b/src/lib/crypto/builtin/Makefile.in @@ -0,0 +1,51 @@ +mydir=lib$(S)crypto$(S)builtin +BUILDTOP=$(REL)..$(S)..$(S).. +SUBDIRS=camellia des aes md4 md5 sha1 sha2 enc_provider hash_provider +LOCALINCLUDES = -I$(srcdir)/../krb -I$(srcdir) + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR = builtin +##DOS##OBJFILE = ..\$(OUTPRE)builtin.lst + +STLIBOBJS=\ + hmac.o \ + init.o \ + pbkdf2.o + +OBJS=\ + $(OUTPRE)hmac.$(OBJEXT) \ + $(OUTPRE)init.$(OBJEXT) \ + $(OUTPRE)pbkdf2.$(OBJEXT) + +SRCS=\ + $(srcdir)/hmac.c \ + $(srcdir)/init.c \ + $(srcdir)/pbkdf2.c + +STOBJLISTS= des/OBJS.ST md4/OBJS.ST \ + md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST \ + enc_provider/OBJS.ST \ + hash_provider/OBJS.ST \ + aes/OBJS.ST \ + camellia/OBJS.ST \ + OBJS.ST + +SUBDIROBJLISTS= des/OBJS.ST md4/OBJS.ST \ + md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST \ + enc_provider/OBJS.ST \ + hash_provider/OBJS.ST \ + aes/OBJS.ST \ + camellia/OBJS.ST + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@lib_frag@ +@libobj_frag@ + diff --git a/src/lib/crypto/builtin/aes/Makefile.in b/src/lib/crypto/builtin/aes/Makefile.in new file mode 100644 index 000000000000..915994b0f5cf --- /dev/null +++ b/src/lib/crypto/builtin/aes/Makefile.in @@ -0,0 +1,62 @@ +mydir=lib$(S)crypto$(S)builtin$(S)aes +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\aes +##DOS##OBJFILE = ..\..\$(OUTPRE)aes.lst + +YASM=@YASM@ +AESNI_OBJ=@AESNI_OBJ@ +AESNI_FLAGS=@AESNI_FLAGS@ + +STLIBOBJS=\ + aescrypt.o \ + aestab.o \ + aeskey.o \ + @AESNI_OBJ@ + +OBJS=\ + $(OUTPRE)aescrypt.$(OBJEXT) \ + $(OUTPRE)aestab.$(OBJEXT) \ + $(OUTPRE)aeskey.$(OBJEXT) + +SRCS=\ + $(srcdir)/aescrypt.c \ + $(srcdir)/aestab.c \ + $(srcdir)/aeskey.c \ + +GEN_OBJS=\ + $(OUTPRE)aescrypt.$(OBJEXT) \ + $(OUTPRE)aestab.$(OBJEXT) \ + $(OUTPRE)aeskey.$(OBJEXT) + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs # aes-gen + +iaesx64@SHOBJEXT@: $(srcdir)/iaesx64.s + $(YASM) $(AESNI_FLAGS) -o $@ $(srcdir)/iaesx64.s + +iaesx86@SHOBJEXT@: $(srcdir)/iaesx86.s + $(YASM) $(AESNI_FLAGS) -o $@ $(srcdir)/iaesx86.s + +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 000000000000..573de52b2c36 --- /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 () +{ + unsigned 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) +{ + size_t 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) +{ + unsigned 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) +{ + unsigned 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) +{ + unsigned 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) +{ + unsigned 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) +{ + unsigned 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 () +{ + unsigned 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 () +{ + unsigned 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 () +{ + unsigned 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 000000000000..8f6f426b9218 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aes.h @@ -0,0 +1,98 @@ +/* + * 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 <stdint.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 000000000000..b644b5eb401f --- /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/aescpp.h b/src/lib/crypto/builtin/aes/aescpp.h new file mode 100644 index 000000000000..d556224e47d6 --- /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 000000000000..1f1cf638e028 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aescrypp.c @@ -0,0 +1,488 @@ +/* + * 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 000000000000..35a6818b6ec3 --- /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 000000000000..194f8e54dbe4 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aescrypt.c @@ -0,0 +1,422 @@ +/* + * 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 000000000000..8402b50cfedc --- /dev/null +++ b/src/lib/crypto/builtin/aes/aeskey.c @@ -0,0 +1,370 @@ +/* + * 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 000000000000..cd9c5a7a4aa7 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aeskeypp.c @@ -0,0 +1,400 @@ +/* + * 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 000000000000..6588b7fc8686 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aesopt.h @@ -0,0 +1,852 @@ +/* + * 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 000000000000..0758737db3ca --- /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 000000000000..ef182d641c0d --- /dev/null +++ b/src/lib/crypto/builtin/aes/aestab.c @@ -0,0 +1,493 @@ +/* + * 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 000000000000..fcd5520cd7d3 --- /dev/null +++ b/src/lib/crypto/builtin/aes/deps @@ -0,0 +1,9 @@ +# +# Generated makefile dependencies follow. +# +aescrypt.so aescrypt.po $(OUTPRE)aescrypt.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h aes.h aescrypt.c aesopt.h +aestab.so aestab.po $(OUTPRE)aestab.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + aes.h aesopt.h aestab.c +aeskey.so aeskey.po $(OUTPRE)aeskey.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + aes.h aeskey.c aesopt.h diff --git a/src/lib/crypto/builtin/aes/iaesx64.s b/src/lib/crypto/builtin/aes/iaesx64.s new file mode 100644 index 000000000000..bc7210ab3039 --- /dev/null +++ b/src/lib/crypto/builtin/aes/iaesx64.s @@ -0,0 +1,799 @@ +[bits 64] +[CPU intelnop] + +; Copyright (c) 2010, Intel Corporation +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; * Redistributions of source code must retain the above copyright notice, +; this list of conditions and the following disclaimer. +; * 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. +; * Neither the name of Intel Corporation nor the names of its contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +; IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%define iEncExpandKey128 k5_iEncExpandKey128 +%define iEncExpandKey256 k5_iEncExpandKey256 +%define iDecExpandKey128 k5_iDecExpandKey128 +%define iDecExpandKey256 k5_iDecExpandKey256 +%define iEnc128_CBC k5_iEnc128_CBC +%define iEnc256_CBC k5_iEnc256_CBC +%define iDec128_CBC k5_iDec128_CBC +%define iDec256_CBC k5_iDec256_CBC + +%macro linux_setup 0 +%ifdef __linux__ + mov rcx, rdi + mov rdx, rsi +%endif +%endmacro + +%macro inversekey 1 + movdqu xmm1,%1 + aesimc xmm0,xmm1 + movdqu %1,xmm0 +%endmacro + +%macro aesdeclast1 1 + aesdeclast xmm0,%1 +%endmacro + +%macro aesenclast1 1 + aesenclast xmm0,%1 +%endmacro + +%macro aesdec1 1 + aesdec xmm0,%1 +%endmacro + +%macro aesenc1 1 + aesenc xmm0,%1 +%endmacro + + +%macro aesdeclast1_u 1 + movdqu xmm4,%1 + aesdeclast xmm0,xmm4 +%endmacro + +%macro aesenclast1_u 1 + movdqu xmm4,%1 + aesenclast xmm0,xmm4 +%endmacro + +%macro aesdec1_u 1 + movdqu xmm4,%1 + aesdec xmm0,xmm4 +%endmacro + +%macro aesenc1_u 1 + movdqu xmm4,%1 + aesenc xmm0,xmm4 +%endmacro + +%macro aesdec4 1 + movdqa xmm4,%1 + + aesdec xmm0,xmm4 + aesdec xmm1,xmm4 + aesdec xmm2,xmm4 + aesdec xmm3,xmm4 + +%endmacro + +%macro aesdeclast4 1 + movdqa xmm4,%1 + + aesdeclast xmm0,xmm4 + aesdeclast xmm1,xmm4 + aesdeclast xmm2,xmm4 + aesdeclast xmm3,xmm4 + +%endmacro + + +%macro aesenc4 1 + movdqa xmm4,%1 + + aesenc xmm0,xmm4 + aesenc xmm1,xmm4 + aesenc xmm2,xmm4 + aesenc xmm3,xmm4 + +%endmacro + +%macro aesenclast4 1 + movdqa xmm4,%1 + + aesenclast xmm0,xmm4 + aesenclast xmm1,xmm4 + aesenclast xmm2,xmm4 + aesenclast xmm3,xmm4 + +%endmacro + + +%macro xor_with_input4 1 + movdqu xmm4,[%1] + pxor xmm0,xmm4 + movdqu xmm4,[%1+16] + pxor xmm1,xmm4 + movdqu xmm4,[%1+32] + pxor xmm2,xmm4 + movdqu xmm4,[%1+48] + pxor xmm3,xmm4 +%endmacro + + + +%macro load_and_xor4 2 + movdqa xmm4,%2 + movdqu xmm0,[%1 + 0*16] + pxor xmm0,xmm4 + movdqu xmm1,[%1 + 1*16] + pxor xmm1,xmm4 + movdqu xmm2,[%1 + 2*16] + pxor xmm2,xmm4 + movdqu xmm3,[%1 + 3*16] + pxor xmm3,xmm4 +%endmacro + +%macro store4 1 + movdqu [%1 + 0*16],xmm0 + movdqu [%1 + 1*16],xmm1 + movdqu [%1 + 2*16],xmm2 + movdqu [%1 + 3*16],xmm3 +%endmacro + +%macro copy_round_keys 3 + movdqu xmm4,[%2 + ((%3)*16)] + movdqa [%1 + ((%3)*16)],xmm4 +%endmacro + + +%macro key_expansion_1_192 1 + ;; Assumes the xmm3 includes all zeros at this point. + pshufd xmm2, xmm2, 11111111b + shufps xmm3, xmm1, 00010000b + pxor xmm1, xmm3 + shufps xmm3, xmm1, 10001100b + pxor xmm1, xmm3 + pxor xmm1, xmm2 + movdqu [rdx+%1], xmm1 +%endmacro + +; Calculate w10 and w11 using calculated w9 and known w4-w5 +%macro key_expansion_2_192 1 + movdqa xmm5, xmm4 + pslldq xmm5, 4 + shufps xmm6, xmm1, 11110000b + pxor xmm6, xmm5 + pxor xmm4, xmm6 + pshufd xmm7, xmm4, 00001110b + movdqu [rdx+%1], xmm7 +%endmacro + + +section .rodata +align 16 +shuffle_mask: +DD 0FFFFFFFFh +DD 03020100h +DD 07060504h +DD 0B0A0908h + + + +section .text + +align 16 +key_expansion256: + + pshufd xmm2, xmm2, 011111111b + + movdqa xmm4, xmm1 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pxor xmm1, xmm2 + + movdqu [rdx], xmm1 + add rdx, 0x10 + + aeskeygenassist xmm4, xmm1, 0 + pshufd xmm2, xmm4, 010101010b + + movdqa xmm4, xmm3 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pxor xmm3, xmm2 + + movdqu [rdx], xmm3 + add rdx, 0x10 + + ret + + + +align 16 +key_expansion128: + pshufd xmm2, xmm2, 0xFF; + movdqa xmm3, xmm1 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pxor xmm1, xmm2 + + ; storing the result in the key schedule array + movdqu [rdx], xmm1 + add rdx, 0x10 + ret + + + + + + +align 16 +global iEncExpandKey128 +iEncExpandKey128: + + linux_setup + + movdqu xmm1, [rcx] ; loading the key + + movdqu [rdx], xmm1 + + movdqa xmm5, [shuffle_mask wrt rip] + + add rdx,16 + + aeskeygenassist xmm2, xmm1, 0x1 ; Generating round key 1 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x2 ; Generating round key 2 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x4 ; Generating round key 3 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x8 ; Generating round key 4 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x10 ; Generating round key 5 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x20 ; Generating round key 6 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x40 ; Generating round key 7 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x80 ; Generating round key 8 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x1b ; Generating round key 9 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x36 ; Generating round key 10 + call key_expansion128 + + ret + + + +align 16 +global iDecExpandKey128 +iDecExpandKey128: + + linux_setup + push rcx + push rdx + sub rsp,16+8 + + call iEncExpandKey128 + + add rsp,16+8 + pop rdx + pop rcx + + inversekey [rdx + 1*16] + inversekey [rdx + 2*16] + inversekey [rdx + 3*16] + inversekey [rdx + 4*16] + inversekey [rdx + 5*16] + inversekey [rdx + 6*16] + inversekey [rdx + 7*16] + inversekey [rdx + 8*16] + inversekey [rdx + 9*16] + + ret + + + +align 16 +global iDecExpandKey256 +iDecExpandKey256: + + linux_setup + push rcx + push rdx + sub rsp,16+8 + + call iEncExpandKey256 + + add rsp,16+8 + pop rdx + pop rcx + + inversekey [rdx + 1*16] + inversekey [rdx + 2*16] + inversekey [rdx + 3*16] + inversekey [rdx + 4*16] + inversekey [rdx + 5*16] + inversekey [rdx + 6*16] + inversekey [rdx + 7*16] + inversekey [rdx + 8*16] + inversekey [rdx + 9*16] + inversekey [rdx + 10*16] + inversekey [rdx + 11*16] + inversekey [rdx + 12*16] + inversekey [rdx + 13*16] + + ret + + + + +align 16 +global iEncExpandKey256 +iEncExpandKey256: + + linux_setup + + movdqu xmm1, [rcx] ; loading the key + movdqu xmm3, [rcx+16] + movdqu [rdx], xmm1 ; Storing key in memory where all key schedule will be stored + movdqu [rdx+16], xmm3 + + add rdx,32 + + movdqa xmm5, [shuffle_mask wrt rip] ; this mask is used by key_expansion + + aeskeygenassist xmm2, xmm3, 0x1 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x2 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x4 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x8 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x10 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x20 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x40 ; +; call key_expansion256 + + pshufd xmm2, xmm2, 011111111b + + movdqa xmm4, xmm1 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pxor xmm1, xmm2 + + movdqu [rdx], xmm1 + + + ret + + + +align 16 +global iDec128_CBC +iDec128_CBC: + + linux_setup + sub rsp,16*16+8 + + mov r9,rcx + mov rax,[rcx+24] + movdqu xmm5,[rax] + + mov eax,[rcx+32] ; numblocks + mov rdx,[rcx] + mov r8,[rcx+8] + mov rcx,[rcx+16] + + + sub r8,rdx + + + test eax,eax + jz end_dec128_CBC + + cmp eax,4 + jl lp128decsingle_CBC + + test rcx,0xf + jz lp128decfour_CBC + + copy_round_keys rsp,rcx,0 + copy_round_keys rsp,rcx,1 + copy_round_keys rsp,rcx,2 + copy_round_keys rsp,rcx,3 + copy_round_keys rsp,rcx,4 + copy_round_keys rsp,rcx,5 + copy_round_keys rsp,rcx,6 + copy_round_keys rsp,rcx,7 + copy_round_keys rsp,rcx,8 + copy_round_keys rsp,rcx,9 + copy_round_keys rsp,rcx,10 + mov rcx,rsp + + +align 16 +lp128decfour_CBC: + + test eax,eax + jz end_dec128_CBC + + cmp eax,4 + jl lp128decsingle_CBC + + load_and_xor4 rdx, [rcx+10*16] + add rdx,16*4 + aesdec4 [rcx+9*16] + aesdec4 [rcx+8*16] + aesdec4 [rcx+7*16] + aesdec4 [rcx+6*16] + aesdec4 [rcx+5*16] + aesdec4 [rcx+4*16] + aesdec4 [rcx+3*16] + aesdec4 [rcx+2*16] + aesdec4 [rcx+1*16] + aesdeclast4 [rcx+0*16] + + pxor xmm0,xmm5 + movdqu xmm4,[rdx - 16*4 + 0*16] + pxor xmm1,xmm4 + movdqu xmm4,[rdx - 16*4 + 1*16] + pxor xmm2,xmm4 + movdqu xmm4,[rdx - 16*4 + 2*16] + pxor xmm3,xmm4 + movdqu xmm5,[rdx - 16*4 + 3*16] + + sub eax,4 + store4 r8+rdx-(16*4) + jmp lp128decfour_CBC + + + align 16 +lp128decsingle_CBC: + + movdqu xmm0, [rdx] + movdqa xmm1,xmm0 + movdqu xmm4,[rcx+10*16] + pxor xmm0, xmm4 + aesdec1_u [rcx+9*16] + aesdec1_u [rcx+8*16] + aesdec1_u [rcx+7*16] + aesdec1_u [rcx+6*16] + aesdec1_u [rcx+5*16] + aesdec1_u [rcx+4*16] + aesdec1_u [rcx+3*16] + aesdec1_u [rcx+2*16] + aesdec1_u [rcx+1*16] + aesdeclast1_u [rcx+0*16] + + pxor xmm0,xmm5 + movdqa xmm5,xmm1 + add rdx, 16 + movdqu [r8 + rdx - 16], xmm0 + dec eax + jnz lp128decsingle_CBC + +end_dec128_CBC: + + mov r9,[r9+24] + movdqu [r9],xmm5 + add rsp,16*16+8 + ret + + + +align 16 +global iDec256_CBC +iDec256_CBC: + + linux_setup + sub rsp,16*16+8 + + mov r9,rcx + mov rax,[rcx+24] + movdqu xmm5,[rax] + + mov eax,[rcx+32] ; numblocks + mov rdx,[rcx] + mov r8,[rcx+8] + mov rcx,[rcx+16] + + + sub r8,rdx + + test eax,eax + jz end_dec256_CBC + + cmp eax,4 + jl lp256decsingle_CBC + + test rcx,0xf + jz lp256decfour_CBC + + copy_round_keys rsp,rcx,0 + copy_round_keys rsp,rcx,1 + copy_round_keys rsp,rcx,2 + copy_round_keys rsp,rcx,3 + copy_round_keys rsp,rcx,4 + copy_round_keys rsp,rcx,5 + copy_round_keys rsp,rcx,6 + copy_round_keys rsp,rcx,7 + copy_round_keys rsp,rcx,8 + copy_round_keys rsp,rcx,9 + copy_round_keys rsp,rcx,10 + copy_round_keys rsp,rcx,11 + copy_round_keys rsp,rcx,12 + copy_round_keys rsp,rcx,13 + copy_round_keys rsp,rcx,14 + mov rcx,rsp + +align 16 +lp256decfour_CBC: + + test eax,eax + jz end_dec256_CBC + + cmp eax,4 + jl lp256decsingle_CBC + + load_and_xor4 rdx, [rcx+14*16] + add rdx,16*4 + aesdec4 [rcx+13*16] + aesdec4 [rcx+12*16] + aesdec4 [rcx+11*16] + aesdec4 [rcx+10*16] + aesdec4 [rcx+9*16] + aesdec4 [rcx+8*16] + aesdec4 [rcx+7*16] + aesdec4 [rcx+6*16] + aesdec4 [rcx+5*16] + aesdec4 [rcx+4*16] + aesdec4 [rcx+3*16] + aesdec4 [rcx+2*16] + aesdec4 [rcx+1*16] + aesdeclast4 [rcx+0*16] + + pxor xmm0,xmm5 + movdqu xmm4,[rdx - 16*4 + 0*16] + pxor xmm1,xmm4 + movdqu xmm4,[rdx - 16*4 + 1*16] + pxor xmm2,xmm4 + movdqu xmm4,[rdx - 16*4 + 2*16] + pxor xmm3,xmm4 + movdqu xmm5,[rdx - 16*4 + 3*16] + + sub eax,4 + store4 r8+rdx-(16*4) + jmp lp256decfour_CBC + + + align 16 +lp256decsingle_CBC: + + movdqu xmm0, [rdx] + movdqu xmm4,[rcx+14*16] + movdqa xmm1,xmm0 + pxor xmm0, xmm4 + aesdec1_u [rcx+13*16] + aesdec1_u [rcx+12*16] + aesdec1_u [rcx+11*16] + aesdec1_u [rcx+10*16] + aesdec1_u [rcx+9*16] + aesdec1_u [rcx+8*16] + aesdec1_u [rcx+7*16] + aesdec1_u [rcx+6*16] + aesdec1_u [rcx+5*16] + aesdec1_u [rcx+4*16] + aesdec1_u [rcx+3*16] + aesdec1_u [rcx+2*16] + aesdec1_u [rcx+1*16] + aesdeclast1_u [rcx+0*16] + + pxor xmm0,xmm5 + movdqa xmm5,xmm1 + add rdx, 16 + movdqu [r8 + rdx - 16], xmm0 + dec eax + jnz lp256decsingle_CBC + +end_dec256_CBC: + + mov r9,[r9+24] + movdqu [r9],xmm5 + add rsp,16*16+8 + ret + + + +align 16 +global iEnc128_CBC +iEnc128_CBC: + + linux_setup + sub rsp,16*16+8 + + mov r9,rcx + mov rax,[rcx+24] + movdqu xmm1,[rax] + + mov eax,[rcx+32] ; numblocks + mov rdx,[rcx] + mov r8,[rcx+8] + mov rcx,[rcx+16] + + sub r8,rdx + + + test rcx,0xf + jz lp128encsingle_CBC + + copy_round_keys rsp,rcx,0 + copy_round_keys rsp,rcx,1 + copy_round_keys rsp,rcx,2 + copy_round_keys rsp,rcx,3 + copy_round_keys rsp,rcx,4 + copy_round_keys rsp,rcx,5 + copy_round_keys rsp,rcx,6 + copy_round_keys rsp,rcx,7 + copy_round_keys rsp,rcx,8 + copy_round_keys rsp,rcx,9 + copy_round_keys rsp,rcx,10 + mov rcx,rsp + + + align 16 + +lp128encsingle_CBC: + + movdqu xmm0, [rdx] + movdqu xmm4,[rcx+0*16] + add rdx, 16 + pxor xmm0, xmm1 + pxor xmm0, xmm4 + aesenc1 [rcx+1*16] + aesenc1 [rcx+2*16] + aesenc1 [rcx+3*16] + aesenc1 [rcx+4*16] + aesenc1 [rcx+5*16] + aesenc1 [rcx+6*16] + aesenc1 [rcx+7*16] + aesenc1 [rcx+8*16] + aesenc1 [rcx+9*16] + aesenclast1 [rcx+10*16] + movdqa xmm1,xmm0 + + ; Store output encrypted data into CIPHERTEXT array + movdqu [r8+rdx-16], xmm0 + dec eax + jnz lp128encsingle_CBC + + mov r9,[r9+24] + movdqu [r9],xmm1 + add rsp,16*16+8 + ret + + + +align 16 +global iEnc256_CBC +iEnc256_CBC: + + linux_setup + sub rsp,16*16+8 + + mov r9,rcx + mov rax,[rcx+24] + movdqu xmm1,[rax] + + mov eax,[rcx+32] ; numblocks + mov rdx,[rcx] + mov r8,[rcx+8] + mov rcx,[rcx+16] + + sub r8,rdx + + test rcx,0xf + jz lp256encsingle_CBC + + copy_round_keys rsp,rcx,0 + copy_round_keys rsp,rcx,1 + copy_round_keys rsp,rcx,2 + copy_round_keys rsp,rcx,3 + copy_round_keys rsp,rcx,4 + copy_round_keys rsp,rcx,5 + copy_round_keys rsp,rcx,6 + copy_round_keys rsp,rcx,7 + copy_round_keys rsp,rcx,8 + copy_round_keys rsp,rcx,9 + copy_round_keys rsp,rcx,10 + copy_round_keys rsp,rcx,11 + copy_round_keys rsp,rcx,12 + copy_round_keys rsp,rcx,13 + copy_round_keys rsp,rcx,14 + mov rcx,rsp + + align 16 + +lp256encsingle_CBC: + + movdqu xmm0, [rdx] + movdqu xmm4, [rcx+0*16] + add rdx, 16 + pxor xmm0, xmm1 + pxor xmm0, xmm4 + aesenc1 [rcx+1*16] + aesenc1 [rcx+2*16] + aesenc1 [rcx+3*16] + aesenc1 [rcx+4*16] + aesenc1 [rcx+5*16] + aesenc1 [rcx+6*16] + aesenc1 [rcx+7*16] + aesenc1 [rcx+8*16] + aesenc1 [rcx+9*16] + aesenc1 [rcx+10*16] + aesenc1 [rcx+11*16] + aesenc1 [rcx+12*16] + aesenc1 [rcx+13*16] + aesenclast1 [rcx+14*16] + movdqa xmm1,xmm0 + + ; Store output encrypted data into CIPHERTEXT array + movdqu [r8+rdx-16], xmm0 + dec eax + jnz lp256encsingle_CBC + + mov r9,[r9+24] + movdqu [r9],xmm1 + add rsp,16*16+8 + ret + +; Mark this file as not needing an executable stack. +%ifidn __OUTPUT_FORMAT__,elf +section .note.GNU-stack noalloc noexec nowrite progbits +%endif +%ifidn __OUTPUT_FORMAT__,elf32 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif +%ifidn __OUTPUT_FORMAT__,elf64 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif diff --git a/src/lib/crypto/builtin/aes/iaesx86.s b/src/lib/crypto/builtin/aes/iaesx86.s new file mode 100644 index 000000000000..945942c06413 --- /dev/null +++ b/src/lib/crypto/builtin/aes/iaesx86.s @@ -0,0 +1,842 @@ +[bits 32] +[CPU intelnop] + +; Copyright (c) 2010, Intel Corporation +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; +; * Redistributions of source code must retain the above copyright notice, +; this list of conditions and the following disclaimer. +; * 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. +; * Neither the name of Intel Corporation nor the names of its contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +; IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +%define _iEncExpandKey128 k5_iEncExpandKey128 +%define _iEncExpandKey256 k5_iEncExpandKey256 +%define _iDecExpandKey128 k5_iDecExpandKey128 +%define _iDecExpandKey256 k5_iDecExpandKey256 +%define _iEnc128_CBC k5_iEnc128_CBC +%define _iEnc256_CBC k5_iEnc256_CBC +%define _iDec128_CBC k5_iDec128_CBC +%define _iDec256_CBC k5_iDec256_CBC + +%macro inversekey 1 + movdqu xmm1,%1 + aesimc xmm0,xmm1 + movdqu %1,xmm0 +%endmacro + + +%macro aesdec4 1 + movdqa xmm4,%1 + + aesdec xmm0,xmm4 + aesdec xmm1,xmm4 + aesdec xmm2,xmm4 + aesdec xmm3,xmm4 + +%endmacro + + +%macro aesdeclast4 1 + movdqa xmm4,%1 + + aesdeclast xmm0,xmm4 + aesdeclast xmm1,xmm4 + aesdeclast xmm2,xmm4 + aesdeclast xmm3,xmm4 + +%endmacro + + +%macro aesenc4 1 + movdqa xmm4,%1 + + aesenc xmm0,xmm4 + aesenc xmm1,xmm4 + aesenc xmm2,xmm4 + aesenc xmm3,xmm4 + +%endmacro + +%macro aesenclast4 1 + movdqa xmm4,%1 + + aesenclast xmm0,xmm4 + aesenclast xmm1,xmm4 + aesenclast xmm2,xmm4 + aesenclast xmm3,xmm4 + +%endmacro + + +%macro aesdeclast1 1 + aesdeclast xmm0,%1 +%endmacro + +%macro aesenclast1 1 + aesenclast xmm0,%1 +%endmacro + +%macro aesdec1 1 + aesdec xmm0,%1 +%endmacro + +;abab +%macro aesenc1 1 + aesenc xmm0,%1 +%endmacro + + +%macro aesdeclast1_u 1 + movdqu xmm4,%1 + aesdeclast xmm0,xmm4 +%endmacro + +%macro aesenclast1_u 1 + movdqu xmm4,%1 + aesenclast xmm0,xmm4 +%endmacro + +%macro aesdec1_u 1 + movdqu xmm4,%1 + aesdec xmm0,xmm4 +%endmacro + +%macro aesenc1_u 1 + movdqu xmm4,%1 + aesenc xmm0,xmm4 +%endmacro + + +%macro load_and_xor4 2 + movdqa xmm4,%2 + movdqu xmm0,[%1 + 0*16] + pxor xmm0,xmm4 + movdqu xmm1,[%1 + 1*16] + pxor xmm1,xmm4 + movdqu xmm2,[%1 + 2*16] + pxor xmm2,xmm4 + movdqu xmm3,[%1 + 3*16] + pxor xmm3,xmm4 +%endmacro + + +%macro xor_with_input4 1 + movdqu xmm4,[%1] + pxor xmm0,xmm4 + movdqu xmm4,[%1+16] + pxor xmm1,xmm4 + movdqu xmm4,[%1+32] + pxor xmm2,xmm4 + movdqu xmm4,[%1+48] + pxor xmm3,xmm4 +%endmacro + +%macro store4 1 + movdqu [%1 + 0*16],xmm0 + movdqu [%1 + 1*16],xmm1 + movdqu [%1 + 2*16],xmm2 + movdqu [%1 + 3*16],xmm3 +%endmacro + + +%macro copy_round_keys 3 + movdqu xmm4,[%2 + ((%3)*16)] + movdqa [%1 + ((%3)*16)],xmm4 +%endmacro + +;abab +%macro copy_round_keyx 3 + movdqu xmm4,[%2 + ((%3)*16)] + movdqa %1,xmm4 +%endmacro + + + +%macro key_expansion_1_192 1 + ;; Assumes the xmm3 includes all zeros at this point. + pshufd xmm2, xmm2, 11111111b + shufps xmm3, xmm1, 00010000b + pxor xmm1, xmm3 + shufps xmm3, xmm1, 10001100b + pxor xmm1, xmm3 + pxor xmm1, xmm2 + movdqu [edx+%1], xmm1 +%endmacro + +; Calculate w10 and w11 using calculated w9 and known w4-w5 +%macro key_expansion_2_192 1 + movdqa xmm5, xmm4 + pslldq xmm5, 4 + shufps xmm6, xmm1, 11110000b + pxor xmm6, xmm5 + pxor xmm4, xmm6 + pshufd xmm7, xmm4, 00001110b + movdqu [edx+%1], xmm7 +%endmacro + + + + + +section .rodata +align 16 +shuffle_mask: +DD 0FFFFFFFFh +DD 03020100h +DD 07060504h +DD 0B0A0908h + + +section .text + + + +align 16 +key_expansion256: + + pshufd xmm2, xmm2, 011111111b + + movdqu xmm4, xmm1 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pxor xmm1, xmm2 + + movdqu [edx], xmm1 + add edx, 0x10 + + aeskeygenassist xmm4, xmm1, 0 + pshufd xmm2, xmm4, 010101010b + + movdqu xmm4, xmm3 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pxor xmm3, xmm2 + + movdqu [edx], xmm3 + add edx, 0x10 + + ret + + + +align 16 +key_expansion128: + pshufd xmm2, xmm2, 0xFF; + movdqu xmm3, xmm1 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pxor xmm1, xmm2 + + ; storing the result in the key schedule array + movdqu [edx], xmm1 + add edx, 0x10 + ret + + + +align 16 +global _iEncExpandKey128 +_iEncExpandKey128: + + mov ecx,[esp-4+8] ;input + mov edx,[esp-4+12] ;ctx + + movdqu xmm1, [ecx] ; loading the key + + movdqu [edx], xmm1 + + call .next +.next: + pop ecx + movdqa xmm5, [ecx-.next+shuffle_mask] + + add edx,16 + + aeskeygenassist xmm2, xmm1, 0x1 ; Generating round key 1 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x2 ; Generating round key 2 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x4 ; Generating round key 3 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x8 ; Generating round key 4 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x10 ; Generating round key 5 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x20 ; Generating round key 6 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x40 ; Generating round key 7 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x80 ; Generating round key 8 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x1b ; Generating round key 9 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x36 ; Generating round key 10 + call key_expansion128 + + ret + + + +align 16 +global _iDecExpandKey128 +_iDecExpandKey128: + push DWORD [esp+8] + push DWORD [esp+8] + + call _iEncExpandKey128 + add esp,8 + + mov edx,[esp-4+12] ;ctx + + inversekey [edx + 1*16] + inversekey [edx + 2*16] + inversekey [edx + 3*16] + inversekey [edx + 4*16] + inversekey [edx + 5*16] + inversekey [edx + 6*16] + inversekey [edx + 7*16] + inversekey [edx + 8*16] + inversekey [edx + 9*16] + + ret + + + +align 16 +global _iDecExpandKey256 +_iDecExpandKey256: + push DWORD [esp+8] + push DWORD [esp+8] + + call _iEncExpandKey256 + add esp, 8 + + mov edx, [esp-4+12] ;expanded key + + inversekey [edx + 1*16] + inversekey [edx + 2*16] + inversekey [edx + 3*16] + inversekey [edx + 4*16] + inversekey [edx + 5*16] + inversekey [edx + 6*16] + inversekey [edx + 7*16] + inversekey [edx + 8*16] + inversekey [edx + 9*16] + inversekey [edx + 10*16] + inversekey [edx + 11*16] + inversekey [edx + 12*16] + inversekey [edx + 13*16] + + ret + + + + +align 16 +global _iEncExpandKey256 +_iEncExpandKey256: + mov ecx, [esp-4+8] ;input + mov edx, [esp-4+12] ;expanded key + + + movdqu xmm1, [ecx] ; loading the key + movdqu xmm3, [ecx+16] + movdqu [edx], xmm1 ; Storing key in memory where all key schedule will be stored + movdqu [edx+16], xmm3 + + add edx,32 + + call .next +.next: + pop ecx + movdqa xmm5, [ecx-.next+shuffle_mask] ; this mask is used by key_expansion + + aeskeygenassist xmm2, xmm3, 0x1 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x2 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x4 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x8 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x10 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x20 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x40 ; +; call key_expansion256 + + pshufd xmm2, xmm2, 011111111b + + movdqu xmm4, xmm1 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pxor xmm1, xmm2 + + movdqu [edx], xmm1 + + + ret + + + +align 16 +global _iDec128_CBC +_iDec128_CBC: + mov ecx,[esp-4+8] + + push esi + push edi + push ebp + mov ebp,esp + sub esp,16*16 + and esp,0xfffffff0 + + mov eax,[ecx+12] + movdqu xmm5,[eax] ;iv + + mov eax,[ecx+16] ; numblocks + mov esi,[ecx] + mov edi,[ecx+4] + mov ecx,[ecx+8] + + sub edi,esi + + test eax,eax + jz end_dec128_CBC + + cmp eax,4 + jl lp128decsingle_CBC + + test ecx,0xf + jz lp128decfour_CBC + + copy_round_keys esp,ecx,0 + copy_round_keys esp,ecx,1 + copy_round_keys esp,ecx,2 + copy_round_keys esp,ecx,3 + copy_round_keys esp,ecx,4 + copy_round_keys esp,ecx,5 + copy_round_keys esp,ecx,6 + copy_round_keys esp,ecx,7 + copy_round_keys esp,ecx,8 + copy_round_keys esp,ecx,9 + copy_round_keys esp,ecx,10 + mov ecx,esp + + +align 16 +lp128decfour_CBC: + + test eax,eax + jz end_dec128_CBC + + cmp eax,4 + jl lp128decsingle_CBC + + load_and_xor4 esi, [ecx+10*16] + add esi,16*4 + aesdec4 [ecx+9*16] + aesdec4 [ecx+8*16] + aesdec4 [ecx+7*16] + aesdec4 [ecx+6*16] + aesdec4 [ecx+5*16] + aesdec4 [ecx+4*16] + aesdec4 [ecx+3*16] + aesdec4 [ecx+2*16] + aesdec4 [ecx+1*16] + aesdeclast4 [ecx+0*16] + + pxor xmm0,xmm5 + movdqu xmm4,[esi- 16*4 + 0*16] + pxor xmm1,xmm4 + movdqu xmm4,[esi- 16*4 + 1*16] + pxor xmm2,xmm4 + movdqu xmm4,[esi- 16*4 + 2*16] + pxor xmm3,xmm4 + movdqu xmm5,[esi- 16*4 + 3*16] + + sub eax,4 + store4 esi+edi-(16*4) + jmp lp128decfour_CBC + + + align 16 +lp128decsingle_CBC: + + movdqu xmm0, [esi] + movdqa xmm1,xmm0 + movdqu xmm4,[ecx+10*16] + pxor xmm0, xmm4 + aesdec1_u [ecx+9*16] + aesdec1_u [ecx+8*16] + aesdec1_u [ecx+7*16] + aesdec1_u [ecx+6*16] + aesdec1_u [ecx+5*16] + aesdec1_u [ecx+4*16] + aesdec1_u [ecx+3*16] + aesdec1_u [ecx+2*16] + aesdec1_u [ecx+1*16] + aesdeclast1_u [ecx+0*16] + + pxor xmm0,xmm5 + movdqa xmm5,xmm1 + + add esi, 16 + movdqu [edi+esi - 16], xmm0 + dec eax + jnz lp128decsingle_CBC + +end_dec128_CBC: + + mov esp,ebp + pop ebp + pop edi + pop esi + + mov ecx,[esp-4+8] ; first arg + mov ecx,[ecx+12] + movdqu [ecx],xmm5 ; store last iv for chaining + + ret + + + +align 16 +global _iDec256_CBC +_iDec256_CBC: + mov ecx,[esp-4+8] + + push esi + push edi + push ebp + mov ebp,esp + + sub esp,16*16 + and esp,0xfffffff0 + + mov eax,[ecx+12] + movdqu xmm5,[eax] ;iv + + mov eax,[ecx+16] ; numblocks + mov esi,[ecx] + mov edi,[ecx+4] + mov ecx,[ecx+8] + + sub edi,esi + + test eax,eax + jz end_dec256_CBC + + cmp eax,4 + jl lp256decsingle_CBC + + test ecx,0xf + jz lp256decfour_CBC + + copy_round_keys esp,ecx,0 + copy_round_keys esp,ecx,1 + copy_round_keys esp,ecx,2 + copy_round_keys esp,ecx,3 + copy_round_keys esp,ecx,4 + copy_round_keys esp,ecx,5 + copy_round_keys esp,ecx,6 + copy_round_keys esp,ecx,7 + copy_round_keys esp,ecx,8 + copy_round_keys esp,ecx,9 + copy_round_keys esp,ecx,10 + copy_round_keys esp,ecx,11 + copy_round_keys esp,ecx,12 + copy_round_keys esp,ecx,13 + copy_round_keys esp,ecx,14 + mov ecx,esp + +align 16 +lp256decfour_CBC: + + test eax,eax + jz end_dec256_CBC + + cmp eax,4 + jl lp256decsingle_CBC + + load_and_xor4 esi, [ecx+14*16] + add esi,16*4 + aesdec4 [ecx+13*16] + aesdec4 [ecx+12*16] + aesdec4 [ecx+11*16] + aesdec4 [ecx+10*16] + aesdec4 [ecx+9*16] + aesdec4 [ecx+8*16] + aesdec4 [ecx+7*16] + aesdec4 [ecx+6*16] + aesdec4 [ecx+5*16] + aesdec4 [ecx+4*16] + aesdec4 [ecx+3*16] + aesdec4 [ecx+2*16] + aesdec4 [ecx+1*16] + aesdeclast4 [ecx+0*16] + + pxor xmm0,xmm5 + movdqu xmm4,[esi- 16*4 + 0*16] + pxor xmm1,xmm4 + movdqu xmm4,[esi- 16*4 + 1*16] + pxor xmm2,xmm4 + movdqu xmm4,[esi- 16*4 + 2*16] + pxor xmm3,xmm4 + movdqu xmm5,[esi- 16*4 + 3*16] + + sub eax,4 + store4 esi+edi-(16*4) + jmp lp256decfour_CBC + + + align 16 +lp256decsingle_CBC: + + movdqu xmm0, [esi] + movdqa xmm1,xmm0 + movdqu xmm4, [ecx+14*16] + pxor xmm0, xmm4 + aesdec1_u [ecx+13*16] + aesdec1_u [ecx+12*16] + aesdec1_u [ecx+11*16] + aesdec1_u [ecx+10*16] + aesdec1_u [ecx+9*16] + aesdec1_u [ecx+8*16] + aesdec1_u [ecx+7*16] + aesdec1_u [ecx+6*16] + aesdec1_u [ecx+5*16] + aesdec1_u [ecx+4*16] + aesdec1_u [ecx+3*16] + aesdec1_u [ecx+2*16] + aesdec1_u [ecx+1*16] + aesdeclast1_u [ecx+0*16] + + pxor xmm0,xmm5 + movdqa xmm5,xmm1 + + add esi, 16 + movdqu [edi+esi - 16], xmm0 + dec eax + jnz lp256decsingle_CBC + +end_dec256_CBC: + + + mov esp,ebp + pop ebp + pop edi + pop esi + + mov ecx,[esp-4+8] ; first arg + mov ecx,[ecx+12] + movdqu [ecx],xmm5 ; store last iv for chaining + + ret + + + +align 16 +global _iEnc128_CBC +_iEnc128_CBC: + mov ecx,[esp-4+8] + + push esi + push edi + push ebp + mov ebp,esp + + sub esp,16*16 + and esp,0xfffffff0 + + mov eax,[ecx+12] + movdqu xmm1,[eax] ;iv + + mov eax,[ecx+16] ; numblocks + mov esi,[ecx] + mov edi,[ecx+4] + mov ecx,[ecx+8] + sub edi,esi + + test ecx,0xf + jz lp128encsingle_CBC + + copy_round_keys esp,ecx,0 + copy_round_keys esp,ecx,1 + copy_round_keys esp,ecx,2 + copy_round_keys esp,ecx,3 + copy_round_keys esp,ecx,4 + copy_round_keys esp,ecx,5 + copy_round_keys esp,ecx,6 + copy_round_keys esp,ecx,7 + copy_round_keys esp,ecx,8 + copy_round_keys esp,ecx,9 + copy_round_keys esp,ecx,10 + mov ecx,esp + + align 16 + +lp128encsingle_CBC: + + movdqu xmm0, [esi] + add esi, 16 + pxor xmm0, xmm1 + movdqu xmm4,[ecx+0*16] + pxor xmm0, xmm4 + aesenc1 [ecx+1*16] + aesenc1 [ecx+2*16] + aesenc1 [ecx+3*16] + aesenc1 [ecx+4*16] + aesenc1 [ecx+5*16] + aesenc1 [ecx+6*16] + aesenc1 [ecx+7*16] + aesenc1 [ecx+8*16] + aesenc1 [ecx+9*16] + aesenclast1 [ecx+10*16] + ; Store output encrypted data into CIPHERTEXT array + movdqu [esi+edi-16], xmm0 + movdqa xmm1,xmm0 + dec eax + jnz lp128encsingle_CBC + + + mov esp,ebp + pop ebp + pop edi + pop esi + mov ecx,[esp-4+8] ; first arg + mov ecx,[ecx+12] + movdqu [ecx],xmm1 ; store last iv for chaining + + ret + + + +align 16 +global _iEnc256_CBC +_iEnc256_CBC: + mov ecx,[esp-4+8] ; first arg + + push esi + push edi + push ebp + mov ebp,esp + + sub esp,16*16 + and esp,0xfffffff0 + + mov eax,[ecx+12] + movdqu xmm1,[eax] ;iv + + mov eax,[ecx+16] ; numblocks + mov esi,[ecx] + mov edi,[ecx+4] + mov ecx,[ecx+8] + sub edi,esi + + test ecx,0xf + jz lp256encsingle_CBC + + copy_round_keys esp,ecx,0 + copy_round_keys esp,ecx,1 + copy_round_keys esp,ecx,2 + copy_round_keys esp,ecx,3 + copy_round_keys esp,ecx,4 + copy_round_keys esp,ecx,5 + copy_round_keys esp,ecx,6 + copy_round_keys esp,ecx,7 + copy_round_keys esp,ecx,8 + copy_round_keys esp,ecx,9 + copy_round_keys esp,ecx,10 + copy_round_keys esp,ecx,11 + copy_round_keys esp,ecx,12 + copy_round_keys esp,ecx,13 + copy_round_keys esp,ecx,14 + mov ecx,esp + + align 16 + +lp256encsingle_CBC: + +;abab + movdqu xmm0, [esi] + add esi, 16 + pxor xmm0, xmm1 + movdqu xmm4,[ecx+0*16] + pxor xmm0, xmm4 + aesenc1 [ecx+1*16] + aesenc1 [ecx+2*16] + aesenc1 [ecx+3*16] + aesenc1 [ecx+4*16] + aesenc1 [ecx+5*16] + aesenc1 [ecx+6*16] + aesenc1 [ecx+7*16] + aesenc1 [ecx+8*16] + aesenc1 [ecx+9*16] + aesenc1 [ecx+10*16] + aesenc1 [ecx+11*16] + aesenc1 [ecx+12*16] + aesenc1 [ecx+13*16] + aesenclast1 [ecx+14*16] + ; Store output encrypted data into CIPHERTEXT array + movdqu [esi+edi-16], xmm0 + movdqa xmm1,xmm0 + dec eax + jnz lp256encsingle_CBC + + + mov esp,ebp + pop ebp + pop edi + pop esi + mov ecx,[esp-4+8] + mov ecx,[ecx+12] + movdqu [ecx],xmm1 ; store last iv for chaining + + ret + +; Mark this file as not needing an executable stack. +%ifidn __OUTPUT_FORMAT__,elf +section .note.GNU-stack noalloc noexec nowrite progbits +%endif +%ifidn __OUTPUT_FORMAT__,elf32 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif +%ifidn __OUTPUT_FORMAT__,elf64 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif diff --git a/src/lib/crypto/builtin/camellia/Makefile.in b/src/lib/crypto/builtin/camellia/Makefile.in new file mode 100644 index 000000000000..5d3b14cf1ce7 --- /dev/null +++ b/src/lib/crypto/builtin/camellia/Makefile.in @@ -0,0 +1,41 @@ +thisconfigdir=../../../.. +myfulldir=lib/crypto/builtin/camellia +mydir=lib$(S)crypto$(S)builtin$(S)camellia +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/../aes + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\camellia +##DOS##OBJFILE = ..\..\$(OUTPRE)camellia.lst + +STLIBOBJS= camellia.o + +OBJS= $(OUTPRE)camellia.$(OBJEXT) + +SRCS= $(srcdir)/camellia.c + +GEN_OBJS= $(OUTPRE)camellia.$(OBJEXT) + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs # camellia-gen + +includes: depend + +depend: $(SRCS) + +camellia-gen: camellia-gen.o $(GEN_OBJS) + $(CC_LINK) -o camellia-gen camellia-gen.o $(GEN_OBJS) + +run-camellia-gen: camellia-gen + ./camellia-gen > kresults.out + +check: run-camellia-gen + + +clean-unix:: clean-libobjs + +clean: + -$(RM) camellia-gen camellia-gen.o kresults.out + +@libobj_frag@ diff --git a/src/lib/crypto/builtin/camellia/camellia-gen.c b/src/lib/crypto/builtin/camellia/camellia-gen.c new file mode 100644 index 000000000000..23b69c174129 --- /dev/null +++ b/src/lib/crypto/builtin/camellia/camellia-gen.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2009 + * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved. + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include "camellia.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]; +camellia_ctx ctx, dctx; + +static void init () +{ + size_t i, j; + cam_rval 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 = camellia_enc_key (key, sizeof(key), &ctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = camellia_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) +{ + size_t 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] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + static const unsigned char input[16] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + static const unsigned char expected[16] = { + 0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73, + 0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43 + }; + unsigned char output[16]; + unsigned char tmp[16]; + camellia_ctx fipsctx; + int r; + + printf ("FIPS test:\nkey:"); + hexdump (fipskey, 16); + printf ("\ninput:"); + hexdump (input, 16); + r = camellia_enc_key (fipskey, sizeof(fipskey), &fipsctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = camellia_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 = camellia_dec_key (fipskey, sizeof(fipskey), &fipsctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = camellia_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) +{ + size_t 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) +{ + size_t i; + cam_rval r; + for (i = 0; i < len; i += 16) { + r = camellia_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) +{ + size_t i; + cam_rval r; + for (i = 0; i < len; i += 16) { + r = camellia_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) +{ + size_t i; + cam_rval 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 = camellia_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) +{ + size_t i; + cam_rval r; + unsigned char tmp[B]; + memcpy (tmp, iv, B); + for (i = 0; i < len; i += B) { + r = camellia_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 = camellia_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 = camellia_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 = camellia_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 = camellia_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 () +{ + size_t 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", (int)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 () +{ + size_t 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", (int)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 () +{ + size_t 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", (int)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/camellia/camellia.c b/src/lib/crypto/builtin/camellia/camellia.c new file mode 100644 index 000000000000..88dfe99ad9ad --- /dev/null +++ b/src/lib/crypto/builtin/camellia/camellia.c @@ -0,0 +1,1539 @@ +/* lib/crypto/builtin/camellia/camellia.c - Camellia version 1.2.0 */ +/* + * Copyright (c) 2006,2007,2009 + * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer as + * the first lines of this file unmodified. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY NTT ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Algorithm Specification + * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html + */ + + +#include <string.h> +#include <stdlib.h> + +#include "camellia.h" + +/* key constants */ + +#define CAMELLIA_SIGMA1L (0xA09E667FL) +#define CAMELLIA_SIGMA1R (0x3BCC908BL) +#define CAMELLIA_SIGMA2L (0xB67AE858L) +#define CAMELLIA_SIGMA2R (0x4CAA73B2L) +#define CAMELLIA_SIGMA3L (0xC6EF372FL) +#define CAMELLIA_SIGMA3R (0xE94F82BEL) +#define CAMELLIA_SIGMA4L (0x54FF53A5L) +#define CAMELLIA_SIGMA4R (0xF1D36F1CL) +#define CAMELLIA_SIGMA5L (0x10E527FAL) +#define CAMELLIA_SIGMA5R (0xDE682D1DL) +#define CAMELLIA_SIGMA6L (0xB05688C2L) +#define CAMELLIA_SIGMA6R (0xB3E6C1FDL) + +/* + * macros + */ + + +#if defined(_MSC_VER) + +# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +# define GETU32(p) SWAP(*((u32 *)(p))) +# define PUTU32(ct, st) {*((u32 *)(ct)) = SWAP((st));} + +#else /* not MS-VC */ + +# define GETU32(pt) \ + (((u32)(pt)[0] << 24) \ + ^ ((u32)(pt)[1] << 16) \ + ^ ((u32)(pt)[2] << 8) \ + ^ ((u32)(pt)[3])) + +# define PUTU32(ct, st) { \ + (ct)[0] = (u8)((st) >> 24); \ + (ct)[1] = (u8)((st) >> 16); \ + (ct)[2] = (u8)((st) >> 8); \ + (ct)[3] = (u8)(st); } + +#endif + +#define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2]) +#define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1]) + +/* rotation right shift 1byte */ +#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24)) +/* rotation left shift 1bit */ +#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31)) +/* rotation left shift 1byte */ +#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24)) + +#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + ll = (ll << bits) + (lr >> (32 - bits)); \ + lr = (lr << bits) + (rl >> (32 - bits)); \ + rl = (rl << bits) + (rr >> (32 - bits)); \ + rr = (rr << bits) + (w0 >> (32 - bits)); \ + } while(0) + +#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + w1 = lr; \ + ll = (lr << (bits - 32)) + (rl >> (64 - bits)); \ + lr = (rl << (bits - 32)) + (rr >> (64 - bits)); \ + rl = (rr << (bits - 32)) + (w0 >> (64 - bits)); \ + rr = (w0 << (bits - 32)) + (w1 >> (64 - bits)); \ + } while(0) + +#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)]) +#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)]) +#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)]) +#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)]) + +#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + il = xl ^ kl; \ + ir = xr ^ kr; \ + t0 = il >> 16; \ + t1 = ir >> 16; \ + yl = CAMELLIA_SP1110(ir & 0xff) \ + ^ CAMELLIA_SP0222((t1 >> 8) & 0xff) \ + ^ CAMELLIA_SP3033(t1 & 0xff) \ + ^ CAMELLIA_SP4404((ir >> 8) & 0xff); \ + yr = CAMELLIA_SP1110((t0 >> 8) & 0xff) \ + ^ CAMELLIA_SP0222(t0 & 0xff) \ + ^ CAMELLIA_SP3033((il >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(il & 0xff); \ + yl ^= yr; \ + yr = CAMELLIA_RR8(yr); \ + yr ^= yl; \ + } while(0) + + +/* + * for speed up + * + */ +#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \ + do { \ + t0 = kll; \ + t0 &= ll; \ + lr ^= CAMELLIA_RL1(t0); \ + t1 = klr; \ + t1 |= lr; \ + ll ^= t1; \ + \ + t2 = krr; \ + t2 |= rr; \ + rl ^= t2; \ + t3 = krl; \ + t3 &= rl; \ + rr ^= CAMELLIA_RL1(t3); \ + } while(0) + +#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + ir = CAMELLIA_SP1110(xr & 0xff) \ + ^ CAMELLIA_SP0222((xr >> 24) & 0xff) \ + ^ CAMELLIA_SP3033((xr >> 16) & 0xff) \ + ^ CAMELLIA_SP4404((xr >> 8) & 0xff); \ + il = CAMELLIA_SP1110((xl >> 24) & 0xff) \ + ^ CAMELLIA_SP0222((xl >> 16) & 0xff) \ + ^ CAMELLIA_SP3033((xl >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(xl & 0xff); \ + il ^= kl; \ + ir ^= kr; \ + ir ^= il; \ + il = CAMELLIA_RR8(il); \ + il ^= ir; \ + yl ^= ir; \ + yr ^= il; \ + } while(0) + + +static const u32 camellia_sp1110[256] = { + 0x70707000,0x82828200,0x2c2c2c00,0xececec00, + 0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500, + 0xe4e4e400,0x85858500,0x57575700,0x35353500, + 0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100, + 0x23232300,0xefefef00,0x6b6b6b00,0x93939300, + 0x45454500,0x19191900,0xa5a5a500,0x21212100, + 0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00, + 0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00, + 0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00, + 0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00, + 0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00, + 0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00, + 0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00, + 0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00, + 0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600, + 0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00, + 0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600, + 0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00, + 0x74747400,0x12121200,0x2b2b2b00,0x20202000, + 0xf0f0f000,0xb1b1b100,0x84848400,0x99999900, + 0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200, + 0x34343400,0x7e7e7e00,0x76767600,0x05050500, + 0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100, + 0xd1d1d100,0x17171700,0x04040400,0xd7d7d700, + 0x14141400,0x58585800,0x3a3a3a00,0x61616100, + 0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00, + 0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600, + 0x53535300,0x18181800,0xf2f2f200,0x22222200, + 0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200, + 0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100, + 0x24242400,0x08080800,0xe8e8e800,0xa8a8a800, + 0x60606000,0xfcfcfc00,0x69696900,0x50505000, + 0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00, + 0xa1a1a100,0x89898900,0x62626200,0x97979700, + 0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500, + 0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200, + 0x10101000,0xc4c4c400,0x00000000,0x48484800, + 0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00, + 0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00, + 0x09090900,0x3f3f3f00,0xdddddd00,0x94949400, + 0x87878700,0x5c5c5c00,0x83838300,0x02020200, + 0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300, + 0x73737300,0x67676700,0xf6f6f600,0xf3f3f300, + 0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200, + 0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600, + 0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00, + 0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00, + 0x13131300,0xbebebe00,0x63636300,0x2e2e2e00, + 0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00, + 0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00, + 0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600, + 0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900, + 0x78787800,0x98989800,0x06060600,0x6a6a6a00, + 0xe7e7e700,0x46464600,0x71717100,0xbababa00, + 0xd4d4d400,0x25252500,0xababab00,0x42424200, + 0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00, + 0x72727200,0x07070700,0xb9b9b900,0x55555500, + 0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00, + 0x36363600,0x49494900,0x2a2a2a00,0x68686800, + 0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400, + 0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00, + 0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100, + 0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400, + 0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00, +}; + +static const u32 camellia_sp0222[256] = { + 0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9, + 0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb, + 0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a, + 0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282, + 0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727, + 0x008a8a8a,0x00323232,0x004b4b4b,0x00424242, + 0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c, + 0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b, + 0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f, + 0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d, + 0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe, + 0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434, + 0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595, + 0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a, + 0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad, + 0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a, + 0x00171717,0x001a1a1a,0x00353535,0x00cccccc, + 0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a, + 0x00e8e8e8,0x00242424,0x00565656,0x00404040, + 0x00e1e1e1,0x00636363,0x00090909,0x00333333, + 0x00bfbfbf,0x00989898,0x00979797,0x00858585, + 0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a, + 0x00dadada,0x006f6f6f,0x00535353,0x00626262, + 0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf, + 0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2, + 0x00bdbdbd,0x00363636,0x00222222,0x00383838, + 0x00646464,0x001e1e1e,0x00393939,0x002c2c2c, + 0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444, + 0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565, + 0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323, + 0x00484848,0x00101010,0x00d1d1d1,0x00515151, + 0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0, + 0x00555555,0x00a1a1a1,0x00414141,0x00fafafa, + 0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f, + 0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b, + 0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5, + 0x00202020,0x00898989,0x00000000,0x00909090, + 0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7, + 0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5, + 0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929, + 0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404, + 0x009b9b9b,0x00949494,0x00212121,0x00666666, + 0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7, + 0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5, + 0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c, + 0x00919191,0x006e6e6e,0x008d8d8d,0x00767676, + 0x00030303,0x002d2d2d,0x00dedede,0x00969696, + 0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c, + 0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919, + 0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d, + 0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d, + 0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2, + 0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4, + 0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575, + 0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484, + 0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5, + 0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa, + 0x00f1f1f1,0x00dddddd,0x00595959,0x00141414, + 0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0, + 0x00787878,0x00707070,0x00e3e3e3,0x00494949, + 0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6, + 0x00777777,0x00939393,0x00868686,0x00838383, + 0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9, + 0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d, +}; + +static const u32 camellia_sp3033[256] = { + 0x38003838,0x41004141,0x16001616,0x76007676, + 0xd900d9d9,0x93009393,0x60006060,0xf200f2f2, + 0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a, + 0x75007575,0x06000606,0x57005757,0xa000a0a0, + 0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9, + 0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090, + 0xf600f6f6,0x07000707,0xa700a7a7,0x27002727, + 0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede, + 0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7, + 0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767, + 0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf, + 0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d, + 0x53005353,0xf000f0f0,0x9c009c9c,0x65006565, + 0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e, + 0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b, + 0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6, + 0xc500c5c5,0x86008686,0x4d004d4d,0x33003333, + 0xfd00fdfd,0x66006666,0x58005858,0x96009696, + 0x3a003a3a,0x09000909,0x95009595,0x10001010, + 0x78007878,0xd800d8d8,0x42004242,0xcc00cccc, + 0xef00efef,0x26002626,0xe500e5e5,0x61006161, + 0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282, + 0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898, + 0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb, + 0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0, + 0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e, + 0x19001919,0x87008787,0x4e004e4e,0x0b000b0b, + 0xa900a9a9,0x0c000c0c,0x79007979,0x11001111, + 0x7f007f7f,0x22002222,0xe700e7e7,0x59005959, + 0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8, + 0x12001212,0x04000404,0x74007474,0x54005454, + 0x30003030,0x7e007e7e,0xb400b4b4,0x28002828, + 0x55005555,0x68006868,0x50005050,0xbe00bebe, + 0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb, + 0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca, + 0x70007070,0xff00ffff,0x32003232,0x69006969, + 0x08000808,0x62006262,0x00000000,0x24002424, + 0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded, + 0x45004545,0x81008181,0x73007373,0x6d006d6d, + 0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a, + 0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101, + 0xe600e6e6,0x25002525,0x48004848,0x99009999, + 0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9, + 0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171, + 0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313, + 0x64006464,0x9b009b9b,0x63006363,0x9d009d9d, + 0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5, + 0x89008989,0x5f005f5f,0xb100b1b1,0x17001717, + 0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646, + 0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747, + 0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b, + 0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac, + 0x3c003c3c,0x4c004c4c,0x03000303,0x35003535, + 0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d, + 0x6a006a6a,0x92009292,0xd500d5d5,0x21002121, + 0x44004444,0x51005151,0xc600c6c6,0x7d007d7d, + 0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa, + 0x7c007c7c,0x77007777,0x56005656,0x05000505, + 0x1b001b1b,0xa400a4a4,0x15001515,0x34003434, + 0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252, + 0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd, + 0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0, + 0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a, + 0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f, +}; + +static const u32 camellia_sp4404[256] = { + 0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0, + 0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae, + 0x23230023,0x6b6b006b,0x45450045,0xa5a500a5, + 0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092, + 0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f, + 0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b, + 0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d, + 0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c, + 0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0, + 0x74740074,0x2b2b002b,0xf0f000f0,0x84840084, + 0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076, + 0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004, + 0x14140014,0x3a3a003a,0xdede00de,0x11110011, + 0x32320032,0x9c9c009c,0x53530053,0xf2f200f2, + 0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a, + 0x24240024,0xe8e800e8,0x60600060,0x69690069, + 0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062, + 0x54540054,0x1e1e001e,0xe0e000e0,0x64640064, + 0x10100010,0x00000000,0xa3a300a3,0x75750075, + 0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd, + 0x87870087,0x83830083,0xcdcd00cd,0x90900090, + 0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf, + 0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6, + 0x81810081,0x6f6f006f,0x13130013,0x63630063, + 0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc, + 0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4, + 0x78780078,0x06060006,0xe7e700e7,0x71710071, + 0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d, + 0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac, + 0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1, + 0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043, + 0x15150015,0xadad00ad,0x77770077,0x80800080, + 0x82820082,0xecec00ec,0x27270027,0xe5e500e5, + 0x85850085,0x35350035,0x0c0c000c,0x41410041, + 0xefef00ef,0x93930093,0x19190019,0x21210021, + 0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd, + 0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce, + 0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a, + 0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d, + 0x01010001,0xd6d600d6,0x56560056,0x4d4d004d, + 0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d, + 0x12120012,0x20200020,0xb1b100b1,0x99990099, + 0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005, + 0xb7b700b7,0x31310031,0x17170017,0xd7d700d7, + 0x58580058,0x61610061,0x1b1b001b,0x1c1c001c, + 0x0f0f000f,0x16160016,0x18180018,0x22220022, + 0x44440044,0xb2b200b2,0xb5b500b5,0x91910091, + 0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050, + 0xd0d000d0,0x7d7d007d,0x89890089,0x97970097, + 0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2, + 0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db, + 0x03030003,0xdada00da,0x3f3f003f,0x94940094, + 0x5c5c005c,0x02020002,0x4a4a004a,0x33330033, + 0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2, + 0x9b9b009b,0x26260026,0x37370037,0x3b3b003b, + 0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e, + 0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e, + 0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059, + 0x98980098,0x6a6a006a,0x46460046,0xbaba00ba, + 0x25250025,0x42420042,0xa2a200a2,0xfafa00fa, + 0x07070007,0x55550055,0xeeee00ee,0x0a0a000a, + 0x49490049,0x68680068,0x38380038,0xa4a400a4, + 0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1, + 0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e, +}; + + +/** + * Stuff related to the Camellia key schedule + */ +#define subl(x) subL[(x)] +#define subr(x) subR[(x)] + +void +camellia_setup128(const unsigned char *key, u32 *subkey) +{ + u32 kll, klr, krl, krr; + u32 il, ir, t0, t1, w0, w1; + u32 kw4l, kw4r, dw, tl, tr; + u32 subL[26]; + u32 subR[26]; + + /** + * k == kll || klr || krl || krr (|| is concatination) + */ + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + /** + * generate KL dependent subkeys + */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(4) = kll; subr(4) = klr; + subl(5) = krl; subr(5) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(10) = kll; subr(10) = klr; + subl(11) = krl; subr(11) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(18) = kll; subr(18) = klr; + subl(19) = krl; subr(19) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + + /* generate KA */ + kll = subl(0); klr = subr(0); + krl = subl(1); krr = subr(1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KA dependent subkeys */ + subl(2) = kll; subr(2) = klr; + subl(3) = krl; subr(3) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(8) = kll; subr(8) = klr; + subl(9) = krl; subr(9) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(12) = kll; subr(12) = klr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(20) = kll; subr(20) = klr; + subl(21) = krl; subr(21) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(24) = kll; subr(24) = klr; + subl(25) = krl; subr(25) = krr; + + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(24) ^= subl(1); subr(24) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(25); kw4r = subr(25); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + CamelliaSubkeyL(23) = subl(22); + CamelliaSubkeyR(23) = subr(22); + CamelliaSubkeyL(24) = subl(24) ^ subl(23); + CamelliaSubkeyR(24) = subr(24) ^ subr(23); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + + return; +} + +void +camellia_setup256(const unsigned char *key, u32 *subkey) +{ + u32 kll,klr,krl,krr; /* left half of key */ + u32 krll,krlr,krrl,krrr; /* right half of key */ + u32 il, ir, t0, t1, w0, w1; /* temporary variables */ + u32 kw4l, kw4r, dw, tl, tr; + u32 subL[34]; + u32 subR[34]; + + /** + * key = (kll || klr || krl || krr || krll || krlr || krrl || krrr) + * (|| is concatination) + */ + + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + krll = GETU32(key + 16); + krlr = GETU32(key + 20); + krrl = GETU32(key + 24); + krrr = GETU32(key + 28); + + /* generate KL dependent subkeys */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45); + subl(12) = kll; subr(12) = klr; + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(30) = kll; subr(30) = klr; + subl(31) = krl; subr(31) = krr; + + /* generate KR dependent subkeys */ + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(4) = krll; subr(4) = krlr; + subl(5) = krrl; subr(5) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(8) = krll; subr(8) = krlr; + subl(9) = krrl; subr(9) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(18) = krll; subr(18) = krlr; + subl(19) = krrl; subr(19) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + subl(26) = krll; subr(26) = krlr; + subl(27) = krrl; subr(27) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + + /* generate KA */ + kll = subl(0) ^ krll; klr = subr(0) ^ krlr; + krl = subl(1) ^ krrl; krr = subr(1) ^ krrr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + kll ^= krll; klr ^= krlr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0 ^ krrl; krr ^= w1 ^ krrr; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KB */ + krll ^= kll; krlr ^= klr; + krrl ^= krl; krrr ^= krr; + CAMELLIA_F(krll, krlr, + CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R, + w0, w1, il, ir, t0, t1); + krrl ^= w0; krrr ^= w1; + CAMELLIA_F(krrl, krrr, + CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R, + w0, w1, il, ir, t0, t1); + krll ^= w0; krlr ^= w1; + + /* generate KA dependent subkeys */ + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + subl(24) = klr; subr(24) = krl; + subl(25) = krr; subr(25) = kll; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49); + subl(28) = kll; subr(28) = klr; + subl(29) = krl; subr(29) = krr; + + /* generate KB dependent subkeys */ + subl(2) = krll; subr(2) = krlr; + subl(3) = krrl; subr(3) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(10) = krll; subr(10) = krlr; + subl(11) = krrl; subr(11) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(20) = krll; subr(20) = krlr; + subl(21) = krrl; subr(21) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51); + subl(32) = krll; subr(32) = krlr; + subl(33) = krrl; subr(33) = krrr; + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(1) ^= subr(1) & ~subr(25); + dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw); + subl(27) ^= subl(1); subr(27) ^= subr(1); + subl(29) ^= subl(1); subr(29) ^= subr(1); + subl(31) ^= subl(1); subr(31) ^= subr(1); + subl(32) ^= subl(1); subr(32) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(33); kw4r = subr(33); + subl(30) ^= kw4l; subr(30) ^= kw4r; + subl(28) ^= kw4l; subr(28) ^= kw4r; + subl(26) ^= kw4l; subr(26) ^= kw4r; + kw4l ^= kw4r & ~subr(24); + dw = kw4l & subl(24), kw4r ^= CAMELLIA_RL1(dw); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + tl = subl(26) ^ (subr(26) & ~subr(24)); + dw = tl & subl(24), tr = subr(26) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(23) = subl(22) ^ tl; + CamelliaSubkeyR(23) = subr(22) ^ tr; + CamelliaSubkeyL(24) = subl(24); + CamelliaSubkeyR(24) = subr(24); + CamelliaSubkeyL(25) = subl(25); + CamelliaSubkeyR(25) = subr(25); + tl = subl(23) ^ (subr(23) & ~subr(25)); + dw = tl & subl(25), tr = subr(23) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(26) = tl ^ subl(27); + CamelliaSubkeyR(26) = tr ^ subr(27); + CamelliaSubkeyL(27) = subl(26) ^ subl(28); + CamelliaSubkeyR(27) = subr(26) ^ subr(28); + CamelliaSubkeyL(28) = subl(27) ^ subl(29); + CamelliaSubkeyR(28) = subr(27) ^ subr(29); + CamelliaSubkeyL(29) = subl(28) ^ subl(30); + CamelliaSubkeyR(29) = subr(28) ^ subr(30); + CamelliaSubkeyL(30) = subl(29) ^ subl(31); + CamelliaSubkeyR(30) = subr(29) ^ subr(31); + CamelliaSubkeyL(31) = subl(30); + CamelliaSubkeyR(31) = subr(30); + CamelliaSubkeyL(32) = subl(32) ^ subl(31); + CamelliaSubkeyR(32) = subr(32) ^ subr(31); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + dw = CamelliaSubkeyL(26) ^ CamelliaSubkeyR(26), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(26) = CamelliaSubkeyL(26) ^ dw, CamelliaSubkeyL(26) = dw; + dw = CamelliaSubkeyL(27) ^ CamelliaSubkeyR(27), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(27) = CamelliaSubkeyL(27) ^ dw, CamelliaSubkeyL(27) = dw; + dw = CamelliaSubkeyL(28) ^ CamelliaSubkeyR(28), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(28) = CamelliaSubkeyL(28) ^ dw, CamelliaSubkeyL(28) = dw; + dw = CamelliaSubkeyL(29) ^ CamelliaSubkeyR(29), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(29) = CamelliaSubkeyL(29) ^ dw, CamelliaSubkeyL(29) = dw; + dw = CamelliaSubkeyL(30) ^ CamelliaSubkeyR(30), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw; + dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw; + + return; +} + +void +camellia_setup192(const unsigned char *key, u32 *subkey) +{ + unsigned char kk[32]; + u32 krll, krlr, krrl,krrr; + + memcpy(kk, key, 24); + memcpy((unsigned char *)&krll, key+16,4); + memcpy((unsigned char *)&krlr, key+20,4); + krrl = ~krll; + krrr = ~krlr; + memcpy(kk+24, (unsigned char *)&krrl, 4); + memcpy(kk+28, (unsigned char *)&krrr, 4); + camellia_setup256(kk, subkey); + return; +} + + +/** + * Stuff related to camellia encryption/decryption + * + * "io" must be 4byte aligned and big-endian data. + */ +void +camellia_encrypt128(const u32 *subkey, u32 *io) +{ + u32 il, ir, t0, t1; + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + /* main iteration */ + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(24); + io[3] ^= CamelliaSubkeyR(24); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +void +camellia_decrypt128(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(24); + io[1] ^= CamelliaSubkeyR(24); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/** + * stuff for 192 and 256bit encryption/decryption + */ +void +camellia_encrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(32); + io[3] ^= CamelliaSubkeyR(32); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +void +camellia_decrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(32); + io[1] ^= CamelliaSubkeyR(32); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/*** + * + * API for compatibility + */ + +void +Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, + KEY_TABLE_TYPE keyTable) +{ + switch(keyBitLength) { + case 128: + camellia_setup128(rawKey, keyTable); + break; + case 192: + camellia_setup192(rawKey, keyTable); + break; + case 256: + camellia_setup256(rawKey, keyTable); + break; + default: + break; + } +} + + +void +Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, + unsigned char *ciphertext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(plaintext); + tmp[1] = GETU32(plaintext + 4); + tmp[2] = GETU32(plaintext + 8); + tmp[3] = GETU32(plaintext + 12); + + switch (keyBitLength) { + case 128: + camellia_encrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_encrypt256(keyTable, tmp); + break; + default: + break; + } + + PUTU32(ciphertext, tmp[0]); + PUTU32(ciphertext + 4, tmp[1]); + PUTU32(ciphertext + 8, tmp[2]); + PUTU32(ciphertext + 12, tmp[3]); +} + +void +Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *ciphertext, + const KEY_TABLE_TYPE keyTable, + unsigned char *plaintext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(ciphertext); + tmp[1] = GETU32(ciphertext + 4); + tmp[2] = GETU32(ciphertext + 8); + tmp[3] = GETU32(ciphertext + 12); + + switch (keyBitLength) { + case 128: + camellia_decrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_decrypt256(keyTable, tmp); + break; + default: + break; + } + PUTU32(plaintext, tmp[0]); + PUTU32(plaintext + 4, tmp[1]); + PUTU32(plaintext + 8, tmp[2]); + PUTU32(plaintext + 12, tmp[3]); +} + +cam_rval +camellia_blk_len(unsigned int blen, camellia_ctx cx[1]){ + if(blen != 16) return camellia_bad; + return camellia_good; +} + +cam_rval +camellia_enc_key(const unsigned char in_key[], unsigned int klen, + camellia_ctx cx[1]){ + switch(klen){ + case 16: + camellia_setup128(in_key, cx->k_sch); + cx->keybitlen = 128; + break; + case 24: + camellia_setup192(in_key, cx->k_sch); + cx->keybitlen = 192; + break; + case 32: + camellia_setup256(in_key, cx->k_sch); + cx->keybitlen = 256; + break; + default: + return camellia_bad; + } + return camellia_good; +} + +cam_rval +camellia_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], + const camellia_ctx cx[1]){ + Camellia_EncryptBlock(cx->keybitlen, in_blk, cx->k_sch, out_blk); + return camellia_good; +} + +cam_rval +camellia_dec_key(const unsigned char in_key[], unsigned int klen, + camellia_ctx cx[1]){ + switch(klen){ + case 16: + camellia_setup128(in_key, cx->k_sch); + cx->keybitlen = 128; + break; + case 24: + camellia_setup192(in_key, cx->k_sch); + cx->keybitlen = 192; + break; + case 32: + camellia_setup256(in_key, cx->k_sch); + cx->keybitlen = 256; + break; + default: + return camellia_bad; + } + return camellia_good; +} + +cam_rval +camellia_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], + const camellia_ctx cx[1]){ + Camellia_DecryptBlock(cx->keybitlen, in_blk, cx->k_sch, out_blk); + return camellia_good; +} diff --git a/src/lib/crypto/builtin/camellia/camellia.h b/src/lib/crypto/builtin/camellia/camellia.h new file mode 100644 index 000000000000..571ba68a669b --- /dev/null +++ b/src/lib/crypto/builtin/camellia/camellia.h @@ -0,0 +1,125 @@ +/* lib/crypto/builtin/camellia/camellia.h - Camellia version 1.2.0 */ +/* + * Copyright (c) 2006,2007,2009 + * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer as + * the first lines of this file unmodified. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY NTT ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HEADER_CAMELLIA_H +#define HEADER_CAMELLIA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#define CAMELLIA_BLOCK_SIZE 16 +#define CAMELLIA_TABLE_BYTE_LEN 272 +#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4) + +#ifndef BLOCK_SIZE +#define BLOCK_SIZE CAMELLIA_BLOCK_SIZE +#endif + +typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; + +/* u32 must be 32bit word */ +typedef uint32_t u32; +typedef uint8_t u8; + +/* For the Kerberos 5 tree, hide the Camellia symbol names. */ +#define camellia_setup128 k5_camellia_setup128 +#define camellia_setup192 k5_camellia_setup192 +#define camellia_setup256 k5_camellia_setup256 +#define camellia_encrypt128 k5_camellia_encrypt128 +#define camellia_decrypt128 k5_camellia_decrypt128 +#define camellia_encrypt256 k5_camellia_encrypt256 +#define camellia_decrypt256 k5_camellia_decrypt256 +#define Camellia_Ekeygen k5_Camellia_Ekeygen +#define Camellia_EncryptBlock k5_Camellia_EncryptBlock +#define Camellia_DecryptBlock k5_Camellia_DecryptBlock + +void camellia_setup128(const unsigned char *key, u32 *subkey); +void camellia_setup192(const unsigned char *key, u32 *subkey); +void camellia_setup256(const unsigned char *key, u32 *subkey); +void camellia_encrypt128(const u32 *subkey, u32 *io); +void camellia_decrypt128(const u32 *subkey, u32 *io); +void camellia_encrypt256(const u32 *subkey, u32 *io); +void camellia_decrypt256(const u32 *subkey, u32 *io); + +void Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, + KEY_TABLE_TYPE keyTable); + +void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, + unsigned char *cipherText); + +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *cipherText, + const KEY_TABLE_TYPE keyTable, + unsigned char *plaintext); + + +typedef uint16_t cam_fret; /* type for function return value */ +#define camellia_good 1 +#define camellia_bad 1 +#ifndef CAMELLIA_DLL /* implement normal or DLL functions */ +#define cam_rval cam_fret +#else +#define cam_rval cam_fret __declspec(dllexport) _stdcall +#endif + +typedef struct /* the Camellia context for encryption */ +{ + uint32_t k_sch[CAMELLIA_TABLE_WORD_LEN]; /* the encryption key schedule */ + int keybitlen; /* bitlength of key */ +} camellia_ctx; + + +/* for Kerberos 5 tree -- hide names! */ +#define camellia_blk_len krb5int_camellia_blk_len +#define camellia_enc_key krb5int_camellia_enc_key +#define camellia_enc_blk krb5int_camellia_enc_blk +#define camellia_dec_key krb5int_camellia_dec_key +#define camellia_dec_blk krb5int_camellia_dec_blk + +cam_rval camellia_blk_len(unsigned int blen, camellia_ctx cx[1]); +cam_rval camellia_enc_key(const unsigned char in_key[], unsigned int klen, + camellia_ctx cx[1]); +cam_rval camellia_enc_blk(const unsigned char in_blk[], + unsigned char out_blk[], + const camellia_ctx cx[1]); +cam_rval camellia_dec_key(const unsigned char in_key[], unsigned int klen, + camellia_ctx cx[1]); +cam_rval camellia_dec_blk(const unsigned char in_blk[], + unsigned char out_blk[], + const camellia_ctx cx[1]); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_CAMELLIA_H */ diff --git a/src/lib/crypto/builtin/camellia/deps b/src/lib/crypto/builtin/camellia/deps new file mode 100644 index 000000000000..ff62c7274039 --- /dev/null +++ b/src/lib/crypto/builtin/camellia/deps @@ -0,0 +1,5 @@ +# +# Generated makefile dependencies follow. +# +camellia.so camellia.po $(OUTPRE)camellia.$(OBJEXT): \ + camellia.c camellia.h diff --git a/src/lib/crypto/builtin/crypto_mod.h b/src/lib/crypto/builtin/crypto_mod.h new file mode 100644 index 000000000000..f85e32215572 --- /dev/null +++ b/src/lib/crypto/builtin/crypto_mod.h @@ -0,0 +1,39 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/crypto_mod.h - Builtin crypto module declarations */ +/* + * Copyright (C) 2011 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. + */ + +/* + * This header is included from lib/crypto/krb/crypto_int.h to provide + * module-specific declarations. It is not included directly from source + * files. + */ + +#ifndef CRYPTO_MOD_H +#define CRYPTO_MOD_H + +#include <aes/aes.h> +#include <sha2/sha2.h> + +#endif /* CRYPTO_MOD_H */ diff --git a/src/lib/crypto/builtin/deps b/src/lib/crypto/builtin/deps new file mode 100644 index 000000000000..54e242ef1f16 --- /dev/null +++ b/src/lib/crypto/builtin/deps @@ -0,0 +1,36 @@ +# +# Generated makefile dependencies follow. +# +hmac.so hmac.po $(OUTPRE)hmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(srcdir)/aes/aes.h $(srcdir)/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_mod.h hmac.c +init.so init.po $(OUTPRE)init.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(srcdir)/aes/aes.h $(srcdir)/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_mod.h init.c +pbkdf2.so pbkdf2.po $(OUTPRE)pbkdf2.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(srcdir)/aes/aes.h $(srcdir)/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_mod.h pbkdf2.c diff --git a/src/lib/crypto/builtin/des/ISSUES b/src/lib/crypto/builtin/des/ISSUES new file mode 100644 index 000000000000..157891103345 --- /dev/null +++ b/src/lib/crypto/builtin/des/ISSUES @@ -0,0 +1,13 @@ +Issues to be addressed for src/lib/crypto/des: -*- text -*- + + +"const" could be used in more places + + +Array types are used in calling interfaces. Under ANSI C, a value of +type "arraytype *" cannot be assigned to a variable of type "const +arraytype *", so we get compilation warnings. + +Possible fix: Rewrite internal interfaces to not use arrays this way. +Provide external routines compatible with old API, but not using +const? diff --git a/src/lib/crypto/builtin/des/Makefile.in b/src/lib/crypto/builtin/des/Makefile.in new file mode 100644 index 000000000000..ed25dab7c8c8 --- /dev/null +++ b/src/lib/crypto/builtin/des/Makefile.in @@ -0,0 +1,80 @@ +mydir=lib$(S)crypto$(S)builtin$(S)des +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../krb + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\des +##DOS##OBJFILE = ..\..\$(OUTPRE)des.lst + +STLIBOBJS=\ + d3_aead.o \ + d3_kysched.o \ + des_keys.o \ + f_aead.o \ + f_cksum.o \ + f_parity.o \ + f_sched.o \ + f_tables.o \ + key_sched.o \ + weak_key.o + +OBJS= $(OUTPRE)d3_aead.$(OBJEXT) \ + $(OUTPRE)d3_kysched.$(OBJEXT) \ + $(OUTPRE)des_keys.$(OBJEXT) \ + $(OUTPRE)f_aead.$(OBJEXT) \ + $(OUTPRE)f_cksum.$(OBJEXT) \ + $(OUTPRE)f_parity.$(OBJEXT) \ + $(OUTPRE)f_sched.$(OBJEXT) \ + $(OUTPRE)f_tables.$(OBJEXT) \ + $(OUTPRE)key_sched.$(OBJEXT) \ + $(OUTPRE)weak_key.$(OBJEXT) + +SRCS= $(srcdir)/d3_aead.c \ + $(srcdir)/d3_kysched.c \ + $(srcdir)/des_keys.c \ + $(srcdir)/f_aead.c \ + $(srcdir)/f_cksum.c \ + $(srcdir)/f_parity.c \ + $(srcdir)/f_sched.c \ + $(srcdir)/f_tables.c \ + $(srcdir)/key_sched.c \ + $(srcdir)/weak_key.c + +EXTRADEPSRCS = $(srcdir)/destest.c $(srcdir)/f_cbc.c $(srcdir)/t_verify.c + +##DOS##LIBOBJS = $(OBJS) + +TOBJS = $(OUTPRE)key_sched.$(OBJEXT) $(OUTPRE)f_sched.$(OBJEXT) \ + $(OUTPRE)f_cbc.$(OBJEXT) $(OUTPRE)f_tables.$(OBJEXT) \ + $(OUTPRE)f_cksum.$(OBJEXT) + +verify$(EXEEXT): t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \ + $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB) + $(CC_LINK) -o $@ t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \ + -lcom_err $(SUPPORT_LIB) + +destest$(EXEEXT): destest.$(OBJEXT) $(TOBJS) $(SUPPORT_DEPLIB) + $(CC_LINK) -o $@ destest.$(OBJEXT) $(TOBJS) $(SUPPORT_LIB) + +all-unix: all-libobjs + +check-unix: verify destest + $(RUN_TEST) ./verify -z + $(RUN_TEST) ./verify -m + $(RUN_TEST) ./verify + $(RUN_TEST) ./destest < $(srcdir)/keytest.data + +includes: depend + +depend: $(SRCS) + +check-windows: + +clean: + $(RM) destest.$(OBJEXT) destest$(EXEEXT) verify$(EXEEXT) \ + t_verify.$(OBJEXT) $(TOBJS) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/src/lib/crypto/builtin/des/d3_aead.c b/src/lib/crypto/builtin/des/d3_aead.c new file mode 100644 index 000000000000..bddf75a474e8 --- /dev/null +++ b/src/lib/crypto/builtin/des/d3_aead.c @@ -0,0 +1,133 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2008 by the Massachusetts Institute of Technology. + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. 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 Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "crypto_int.h" +#include "des_int.h" +#include "f_tables.h" + +void +krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp1, *kp2, *kp3; + const unsigned char *ip; + struct iov_cursor cursor; + unsigned char block[MIT_DES_BLOCK_LENGTH]; + + /* Get key pointers here. These won't need to be reinitialized. */ + kp1 = (const unsigned DES_INT32 *)ks1; + kp2 = (const unsigned DES_INT32 *)ks2; + kp3 = (const unsigned DES_INT32 *)ks3; + + /* Initialize left and right with the contents of the initial vector. */ + ip = (ivec != NULL) ? ivec : mit_des_zeroblock; + left = load_32_be(ip); + right = load_32_be(ip + 4); + + k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); + while (k5_iov_cursor_get(&cursor, block)) { + /* xor this block with the previous ciphertext. */ + left ^= load_32_be(block); + right ^= load_32_be(block + 4); + + /* Encrypt what we have and store it back into block. */ + DES_DO_ENCRYPT(left, right, kp1); + DES_DO_DECRYPT(left, right, kp2); + DES_DO_ENCRYPT(left, right, kp3); + store_32_be(left, block); + store_32_be(right, block + 4); + + k5_iov_cursor_put(&cursor, block); + } + + if (ivec != NULL) { + store_32_be(left, ivec); + store_32_be(right, ivec + 4); + } +} + +void +krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp1, *kp2, *kp3; + const unsigned char *ip; + unsigned DES_INT32 ocipherl, ocipherr; + unsigned DES_INT32 cipherl, cipherr; + struct iov_cursor cursor; + unsigned char block[MIT_DES_BLOCK_LENGTH]; + + /* Get key pointers here. These won't need to be reinitialized. */ + kp1 = (const unsigned DES_INT32 *)ks1; + kp2 = (const unsigned DES_INT32 *)ks2; + kp3 = (const unsigned DES_INT32 *)ks3; + + /* + * Decrypting is harder than encrypting because of + * the necessity of remembering a lot more things. + * Should think about this a little more... + */ + + /* Prime the old cipher with ivec.*/ + ip = (ivec != NULL) ? ivec : mit_des_zeroblock; + ocipherl = load_32_be(ip); + ocipherr = load_32_be(ip + 4); + + k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); + while (k5_iov_cursor_get(&cursor, block)) { + /* Split this block into left and right. */ + cipherl = left = load_32_be(block); + cipherr = right = load_32_be(block + 4); + + /* Decrypt and xor with the old cipher to get plain text. */ + DES_DO_DECRYPT(left, right, kp3); + DES_DO_ENCRYPT(left, right, kp2); + DES_DO_DECRYPT(left, right, kp1); + left ^= ocipherl; + right ^= ocipherr; + + /* Store the encrypted halves back into block. */ + store_32_be(left, block); + store_32_be(right, block + 4); + + /* Save current cipher block halves. */ + ocipherl = cipherl; + ocipherr = cipherr; + + k5_iov_cursor_put(&cursor, block); + } + + if (ivec != NULL) { + store_32_be(ocipherl, ivec); + store_32_be(ocipherr, ivec + 4); + } +} diff --git a/src/lib/crypto/builtin/des/d3_kysched.c b/src/lib/crypto/builtin/des/d3_kysched.c new file mode 100644 index 000000000000..ebd1050b1fd9 --- /dev/null +++ b/src/lib/crypto/builtin/des/d3_kysched.c @@ -0,0 +1,51 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. 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 Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "k5-int.h" +#include "des_int.h" + +int +mit_des3_key_sched(mit_des3_cblock k, mit_des3_key_schedule schedule) +{ + mit_des_make_key_sched(k[0],schedule[0]); + mit_des_make_key_sched(k[1],schedule[1]); + mit_des_make_key_sched(k[2],schedule[2]); + + if (!mit_des_check_key_parity(k[0])) /* bad parity --> return -1 */ + return(-1); + if (mit_des_is_weak_key(k[0])) + return(-2); + + if (!mit_des_check_key_parity(k[1])) + return(-1); + if (mit_des_is_weak_key(k[1])) + return(-2); + + if (!mit_des_check_key_parity(k[2])) + return(-1); + if (mit_des_is_weak_key(k[2])) + return(-2); + + /* if key was good, return 0 */ + return 0; +} diff --git a/src/lib/crypto/builtin/des/deps b/src/lib/crypto/builtin/des/deps new file mode 100644 index 000000000000..df2a31dacda9 --- /dev/null +++ b/src/lib/crypto/builtin/des/deps @@ -0,0 +1,148 @@ +# +# Generated makefile dependencies follow. +# +d3_aead.so d3_aead.po $(OUTPRE)d3_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + d3_aead.c des_int.h f_tables.h +d3_kysched.so d3_kysched.po $(OUTPRE)d3_kysched.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + d3_kysched.c des_int.h +des_keys.so des_keys.po $(OUTPRE)des_keys.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../aes/aes.h \ + $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des_int.h des_keys.c +f_aead.so f_aead.po $(OUTPRE)f_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des_int.h f_aead.c f_tables.h +f_cksum.so f_cksum.po $(OUTPRE)f_cksum.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_int.h f_cksum.c \ + f_tables.h +f_parity.so f_parity.po $(OUTPRE)f_parity.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des_int.h f_parity.c +f_sched.so f_sched.po $(OUTPRE)f_sched.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_int.h f_sched.c +f_tables.so f_tables.po $(OUTPRE)f_tables.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des_int.h f_tables.c f_tables.h +key_sched.so key_sched.po $(OUTPRE)key_sched.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des_int.h key_sched.c +weak_key.so weak_key.po $(OUTPRE)weak_key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des_int.h weak_key.c +destest.so destest.po $(OUTPRE)destest.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_int.h destest.c +f_cbc.so f_cbc.po $(OUTPRE)f_cbc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_int.h f_cbc.c \ + f_tables.h +t_verify.so t_verify.po $(OUTPRE)t_verify.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des_int.h t_verify.c diff --git a/src/lib/crypto/builtin/des/des_int.h b/src/lib/crypto/builtin/des/des_int.h new file mode 100644 index 000000000000..0801cb5828c9 --- /dev/null +++ b/src/lib/crypto/builtin/des/des_int.h @@ -0,0 +1,286 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/des_int.h */ +/* + * Copyright 1987, 1988, 1990, 2002 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. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* Private include file for the Data Encryption Standard library. */ + +/* only do the whole thing once */ +#ifndef DES_INTERNAL_DEFS +#define DES_INTERNAL_DEFS + +#include "k5-int.h" +/* + * Begin "mit-des.h" + */ +#ifndef KRB5_MIT_DES__ +#define KRB5_MIT_DES__ + +#if defined(__MACH__) && defined(__APPLE__) +#include <TargetConditionals.h> +#include <AvailabilityMacros.h> +#if TARGET_RT_MAC_CFM +#error "Use KfM 4.0 SDK headers for CFM compilation." +#endif +#if defined(DEPRECATED_IN_MAC_OS_X_VERSION_10_5) && !defined(KRB5_SUPRESS_DEPRECATED_WARNINGS) +#define KRB5INT_DES_DEPRECATED DEPRECATED_IN_MAC_OS_X_VERSION_10_5 +#endif +#endif /* defined(__MACH__) && defined(__APPLE__) */ + +/* Macro to add deprecated attribute to DES types and functions */ +/* Currently only defined on Mac OS X 10.5 and later. */ +#ifndef KRB5INT_DES_DEPRECATED +#define KRB5INT_DES_DEPRECATED +#endif + +#include <limits.h> + +#if UINT_MAX >= 0xFFFFFFFFUL +#define DES_INT32 int +#define DES_UINT32 unsigned int +#else +#define DES_INT32 long +#define DES_UINT32 unsigned long +#endif + +typedef unsigned char des_cblock[8] /* crypto-block size */ +KRB5INT_DES_DEPRECATED; + +/* + * Key schedule. + * + * This used to be + * + * typedef struct des_ks_struct { + * union { DES_INT32 pad; des_cblock _;} __; + * } des_key_schedule[16]; + * + * but it would cause trouble if DES_INT32 were ever more than 4 + * bytes. The reason is that all the encryption functions cast it to + * (DES_INT32 *), and treat it as if it were DES_INT32[32]. If + * 2*sizeof(DES_INT32) is ever more than sizeof(des_cblock), the + * caller-allocated des_key_schedule will be overflowed by the key + * scheduling functions. We can't assume that every platform will + * have an exact 32-bit int, and nothing should be looking inside a + * des_key_schedule anyway. + */ +typedef struct des_ks_struct { DES_INT32 _[2]; } des_key_schedule[16] +KRB5INT_DES_DEPRECATED; + +typedef des_cblock mit_des_cblock; +typedef des_key_schedule mit_des_key_schedule; + +/* Triple-DES structures */ +typedef mit_des_cblock mit_des3_cblock[3]; +typedef mit_des_key_schedule mit_des3_key_schedule[3]; + +#define MIT_DES_ENCRYPT 1 +#define MIT_DES_DECRYPT 0 + +typedef struct mit_des_ran_key_seed { + krb5_encrypt_block eblock; + krb5_data sequence; +} mit_des_random_state; + +/* the first byte of the key is already in the keyblock */ + +#define MIT_DES_BLOCK_LENGTH (8*sizeof(krb5_octet)) +#define MIT_DES_CBC_CRC_PAD_MINIMUM CRC32_CKSUM_LENGTH +/* This used to be 8*sizeof(krb5_octet) */ +#define MIT_DES_KEYSIZE 8 + +#define MIT_DES_CBC_CKSUM_LENGTH (4*sizeof(krb5_octet)) + +#endif /* KRB5_MIT_DES__ */ +/* + * End "mit-des.h" + */ + +/* afsstring2key.c */ +krb5_error_code mit_afs_string_to_key(krb5_keyblock *keyblock, + const krb5_data *data, + const krb5_data *salt); +char *mit_afs_crypt(const char *pw, const char *salt, char *iobuf); + +/* f_cksum.c */ +unsigned long mit_des_cbc_cksum(const krb5_octet *, krb5_octet *, + unsigned long, const mit_des_key_schedule, + const krb5_octet *); + +/* f_cbc.c (used by test programs) */ +int +mit_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, + unsigned long length, const mit_des_key_schedule schedule, + const mit_des_cblock ivec, int enc); + +#define mit_des_zeroblock krb5int_c_mit_des_zeroblock +extern const mit_des_cblock mit_des_zeroblock; + +/* fin_rndkey.c */ +krb5_error_code mit_des_finish_random_key(const krb5_encrypt_block *, + krb5_pointer *); + +/* finish_key.c */ +krb5_error_code mit_des_finish_key(krb5_encrypt_block *); + +/* init_rkey.c */ +krb5_error_code mit_des_init_random_key(const krb5_encrypt_block *, + const krb5_keyblock *, + krb5_pointer *); + +/* key_parity.c */ +void mit_des_fixup_key_parity(mit_des_cblock); +int mit_des_check_key_parity(mit_des_cblock); + +/* key_sched.c */ +int mit_des_key_sched(mit_des_cblock, mit_des_key_schedule); + +/* process_ky.c */ +krb5_error_code mit_des_process_key(krb5_encrypt_block *, + const krb5_keyblock *); + +/* random_key.c */ +krb5_error_code mit_des_random_key(const krb5_encrypt_block *, + krb5_pointer, krb5_keyblock **); + +/* string2key.c */ +krb5_error_code mit_des_string_to_key(const krb5_encrypt_block *, + krb5_keyblock *, const krb5_data *, + const krb5_data *); +krb5_error_code mit_des_string_to_key_int(krb5_keyblock *, const krb5_data *, + const krb5_data *); + +/* weak_key.c */ +int mit_des_is_weak_key(mit_des_cblock); + +/* cmb_keys.c */ +krb5_error_code mit_des_combine_subkeys(const krb5_keyblock *, + const krb5_keyblock *, + krb5_keyblock **); + +/* f_pcbc.c */ +int mit_des_pcbc_encrypt(); + +/* f_sched.c */ +int mit_des_make_key_sched(mit_des_cblock, mit_des_key_schedule); + + +/* misc.c */ +extern void swap_bits(char *); +extern unsigned long long_swap_bits(unsigned long); +extern unsigned long swap_six_bits_to_ansi(unsigned long); +extern unsigned long swap_four_bits_to_ansi(unsigned long); +extern unsigned long swap_bit_pos_1(unsigned long); +extern unsigned long swap_bit_pos_0(unsigned long); +extern unsigned long swap_bit_pos_0_to_ansi(unsigned long); +extern unsigned long rev_swap_bit_pos_0(unsigned long); +extern unsigned long swap_byte_bits(unsigned long); +extern unsigned long swap_long_bytes_bit_number(unsigned long); +#ifdef FILE +/* XXX depends on FILE being a #define! */ +extern void test_set(FILE *, const char *, int, const char *, int); +#endif + +void +krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec); + +void +krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec); + +void +krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec); + +void +krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec); + +void +krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, mit_des_cblock ivec, + mit_des_cblock out); + +/* d3_procky.c */ +krb5_error_code mit_des3_process_key(krb5_encrypt_block *eblock, + const krb5_keyblock *keyblock); + +/* d3_kysched.c */ +int mit_des3_key_sched(mit_des3_cblock key, mit_des3_key_schedule schedule); + +/* d3_str2ky.c */ +krb5_error_code mit_des3_string_to_key(const krb5_encrypt_block *eblock, + krb5_keyblock *keyblock, + const krb5_data *data, + const krb5_data *salt); + +/* u_nfold.c */ +krb5_error_code mit_des_n_fold(const krb5_octet *input, const size_t in_len, + krb5_octet *output, const size_t out_len); + +/* u_rn_key.c */ +int mit_des_is_weak_keyblock(krb5_keyblock *keyblock); + +void mit_des_fixup_keyblock_parity(krb5_keyblock *keyblock); + +krb5_error_code mit_des_set_random_generator_seed(const krb5_data *seed, + krb5_pointer random_state); + +krb5_error_code mit_des_set_random_sequence_number(const krb5_data *sequence, + krb5_pointer random_state); +#endif /*DES_INTERNAL_DEFS*/ diff --git a/src/lib/crypto/builtin/des/des_keys.c b/src/lib/crypto/builtin/des/des_keys.c new file mode 100644 index 000000000000..32b119aade70 --- /dev/null +++ b/src/lib/crypto/builtin/des/des_keys.c @@ -0,0 +1,40 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/des_keys.c - Key functions used by Kerberos code */ +/* + * Copyright (C) 2011 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. + */ + +#include "crypto_int.h" +#include "des_int.h" + +void +k5_des_fixup_key_parity(unsigned char *keybits) +{ + mit_des_fixup_key_parity(keybits); +} + +krb5_boolean +k5_des_is_weak_key(unsigned char *keybits) +{ + return mit_des_is_weak_key(keybits); +} diff --git a/src/lib/crypto/builtin/des/destest.c b/src/lib/crypto/builtin/des/destest.c new file mode 100644 index 000000000000..6eeb070d867f --- /dev/null +++ b/src/lib/crypto/builtin/des/destest.c @@ -0,0 +1,243 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/destest.c */ +/* + * Copyright 1990,1991 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. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* Test a DES implementation against known inputs & outputs. */ + +#include "des_int.h" +#include <stdio.h> + +void convert (char *, unsigned char []); + +void des_cblock_print_file (mit_des_cblock, FILE *); + +krb5_octet zeroblock[8] = {0,0,0,0,0,0,0,0}; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char block1[17], block2[17], block3[17]; +#if 0 + mit_des_cblock key, input, output, output2; +#else + /* Force tests of unaligned accesses. */ + union { unsigned char c[8*4+3]; long l; } u; + unsigned char *ioblocks = u.c; + unsigned char *input = ioblocks+1; + unsigned char *output = ioblocks+10; + unsigned char *output2 = ioblocks+19; + unsigned char *key = ioblocks+27; +#endif + mit_des_key_schedule sched; + int num = 0; + int retval; + + int error = 0; + + while (scanf("%16s %16s %16s", block1, block2, block3) == 3) { + convert(block1, key); + convert(block2, input); + convert(block3, output); + + retval = mit_des_key_sched(key, sched); + if (retval) { + fprintf(stderr, "des test: can't process key: %d\n", retval); + fprintf(stderr, "des test: %s %s %s\n", block1, block2, block3); + exit(1); + } + mit_des_cbc_encrypt((const mit_des_cblock *) input, + (mit_des_cblock *) output2, 8, + sched, zeroblock, 1); + + if (memcmp((char *)output2, (char *)output, 8)) { + fprintf(stderr, + "DES ENCRYPT ERROR, key %s, text %s, real cipher %s, computed cyphertext %02X%02X%02X%02X%02X%02X%02X%02X\n", + block1, block2, block3, + output2[0],output2[1],output2[2],output2[3], + output2[4],output2[5],output2[6],output2[7]); + error++; + } + + /* + * Now try decrypting.... + */ + mit_des_cbc_encrypt((const mit_des_cblock *) output, + (mit_des_cblock *) output2, 8, + sched, zeroblock, 0); + + if (memcmp((char *)output2, (char *)input, 8)) { + fprintf(stderr, + "DES DECRYPT ERROR, key %s, text %s, real cipher %s, computed cleartext %02X%02X%02X%02X%02X%02X%02X%02X\n", + block1, block2, block3, + output2[0],output2[1],output2[2],output2[3], + output2[4],output2[5],output2[6],output2[7]); + error++; + } + + num++; + } + + if (error) + printf("destest: failed to pass the test\n"); + else + printf("destest: %d tests passed successfully\n", num); + + exit( (error > 256 && error % 256) ? 1 : error); +} + +int value[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +void +convert(text, cblock) + char *text; + unsigned char cblock[]; +{ + register int i; + for (i = 0; i < 8; i++) { + if (text[i*2] < 0 || text[i*2] >= 128) + abort (); + if (value[(int) text[i*2]] == -1 || value[(int) text[i*2+1]] == -1) { + printf("Bad value byte %d in %s\n", i, text); + exit(1); + } + cblock[i] = 16*value[(int) text[i*2]] + value[(int) text[i*2+1]]; + } + return; +} + +/* + * Fake out the DES library, for the purposes of testing. + */ + +int +mit_des_is_weak_key(key) + mit_des_cblock key; +{ + return 0; /* fake it out for testing */ +} + +void +des_cblock_print_file(x, fp) + mit_des_cblock x; + FILE *fp; +{ + unsigned char *y = (unsigned char *) x; + register int i = 0; + fprintf(fp," 0x { "); + + while (i++ < 8) { + fprintf(fp,"%x",*y++); + if (i < 8) + fprintf(fp,", "); + } + fprintf(fp," }"); +} + + +#define smask(step) ((1<<step)-1) +#define pstep(x,step) (((x)&smask(step))^(((x)>>step)&smask(step))) +#define parity_char(x) pstep(pstep(pstep((x),4),2),1) + +/* + * des_check_key_parity: returns true iff key has the correct des parity. + * See des_fix_key_parity for the definition of + * correct des parity. + */ +int +mit_des_check_key_parity(key) + register mit_des_cblock key; +{ + unsigned int i; + + for (i=0; i<sizeof(mit_des_cblock); i++) { + if ((key[i] & 1) == parity_char(0xfe&key[i])) { + printf("warning: bad parity key:"); + des_cblock_print_file(key, stdout); + putchar('\n'); + + return 1; + } + } + + return(1); +} + +void +mit_des_fixup_key_parity(key) + register mit_des_cblock key; +{ + unsigned int i; + for (i=0; i<sizeof(mit_des_cblock); i++) + { + key[i] &= 0xfe; + key[i] |= 1^parity_char(key[i]); + } + + return; +} diff --git a/src/lib/crypto/builtin/des/doc/libdes.doc b/src/lib/crypto/builtin/des/doc/libdes.doc new file mode 100644 index 000000000000..70f9f336a1ea --- /dev/null +++ b/src/lib/crypto/builtin/des/doc/libdes.doc @@ -0,0 +1,208 @@ + + How to use the Kerberos encryption library. + + Revised 10/15/85 spm + +1) The following include file is needed: + + /projects/auth/include/des.h (VAX) + --------------- (PC8086) + +2) The encryption library that should be linked to is: + + /projects/auth/lib/libdes.a (VAX) +| /projects/auth/ibm/lib/libdes.a (PC8086 cross-compilation environment) + +3) For each key that may be simultaneously active, + allocate (either compile or malloc) a "Key_schedule" struct, + defined in "des.h" + +4) Create key schedules, as needed, prior to using the encryption + routines, via "des_set_key()". + +5) Setup the input and output areas. Make sure to note the restrictions + on lengths being multiples of eight bytes. + +6) Invoke the encryption/decryption routines, "ecb_encrypt()" + or "cbc_encrypt()" + +7) To generate a cryptographic checksum, use "cbc_cksum()" +/* ---------------------------------------------------------------- */ + + Routine Interfaces-- + +/* ----------------------------------------------------------------- */ + +int + des_set_key(k,schedule) + C_Block *k; + Key_schedule schedule; + + Calculates a key schedule from (all) eight bytes of the input key, and + puts it into the indicated "Key_schedule" struct; + + Make sure to pass valid eight bytes, no padding or other processing + it done. + + The key schedule is then used in subsequent encryption/decryption + operations. Many key schedules may be created and cached for later + use. + + The user is responsible to clear keys and schedules no longer needed + to prevent their disclosure. + +| Checks the parity of the key provided, to make sure it is odd per +| FIPS spec. Returns 0 value for key ok, 1 for key_parity error. + +/* ---------------------------------------------------------------- */ + +int + ecb_encrypt(input,output,schedule,encrypt) + C_Block *input; /* ptr to eight byte input value */ + C_Block *output; /* ptr to eight byte output value */ + int encrypt; /* 0 ==> decrypt, else encrypt */ + Key_schedule schedule; /* addr of key schedule */ + +This is the low level routine that encrypts or decrypts a single 8-byte +block in electronic code book mode. Always transforms the input +data into the output data. + +If encrypt is non-zero, the input (cleartext) is encrypted into the +output (ciphertext) using the specified key_schedule, pre-set via "des_set_key". + +If encrypt is zero, the input (now ciphertext) is decrypted into +the output (now cleartext). + +Input and output may be the same space. + +Does not return any meaningful value. Void is not used for compatibility +with other compilers. + +/* -------------------------------------------------------------- */ + +int + cbc_encrypt(input,output,length,schedule,ivec,encrypt) + + C_Block *input; /* ptr to input data */ + C_Block *output; /* ptr to output data */ + int length; /* desired length, in bytes */ + Key_schedule schedule; /* addr of precomputed schedule */ + C_Block *ivec; /* pointer to 8 byte initialization + * vector + */ + int encrypt /* 0 ==> decrypt; else encrypt*/ + + + If encrypt is non-zero, the routine cipher-block-chain encrypts + the INPUT (cleartext) into the OUTPUT (ciphertext) using the provided + key schedule and initialization vector. If the length is not an integral + multiple of eight bytes, the last block is copied to a temp and zero + filled (highest addresses). The output is ALWAYS an integral multiple + of eight bytes. + + If encrypt is zero, the routine cipher-block chain decrypts the INPUT + (ciphertext) into the OUTPUT (cleartext) using the provided key schedule + and initialization vector. Decryption ALWAYS operates on integral + multiples of 8 bytes, so will round the length provided up to the + appropriate multiple. Consequently, it will always produce the rounded-up + number of bytes of output cleartext. The application must determine if + the output cleartext was zero-padded due to cleartext lengths not integral + multiples of 8. + + No errors or meaningful value are returned. Void is not used for + compatibility with other compilers. + + +/* cbc checksum (MAC) only routine ---------------------------------------- */ +int + cbc_cksum(input,output,length,schedule,ivec) + + C_Block *input; /* >= length bytes of inputtext */ + C_Block *output; /* >= length bytes of outputtext */ + int length; /* in bytes */ + Key_schedule schedule; /* precomputed key schedule */ + C_Block *ivec; /* 8 bytes of ivec */ + + + Produces a cryptographic checksum, 8 bytes, by cipher-block-chain + encrypting the input, discarding the ciphertext output, and only retaining + the last ciphertext 8-byte block. Uses the provided key schedule and ivec. + The input is effectively zero-padded to an integral multiple of + eight bytes, though the original input is not modified. + + No meaningful value is returned. Void is not used for compatibility + with other compilers. + + +/* random_key ----------------------------------------*/ +int + random_key(key) + + C_Block *key; + + The start for the random number generated is set from the current time + in microseconds, then the random number generator is invoked + to create an eight byte output key (not a schedule). The key + generated is set to odd parity per FIPS spec. + + The caller must supply space for the output key, pointed to + by "*key", then after getting a new key, call the des_set_key() + routine when needed. + + No meaningfull value is returned. Void is not used for compatibility + with other compilers. + + +/* string_to_key --------------------------------------------*/ + +int + string_to_key(str,key) + register char *str; + register C_Block *key; + + This routines converts an arbitrary length, null terminated string + to an 8 byte DES key, with each byte parity set to odd, per FIPS spec. + + The algorithm is as follows: + +| Take the first 8 bytes and remove the parity (leaving 56 bits). +| Do the same for the second 8 bytes, and the third, etc. Do this for +| as many sets of 8 bytes as necessary, filling in the remainder of the +| last set with nulls. Fold the second set back on the first (i.e. bit +| 0 over bit 55, and bit 55 over bit 0). Fold the third over the second +| (bit 0 of the third set is now over bit 0 of the first set). Repeat +| until you have done this to all sets. Xor the folded sets. Break the +| result into 8 7 bit bytes, and generate odd parity for each byte. You +| now have 64 bits. Note that DES takes a 64 bit key, and uses only the +| non parity bits. + + +/* read_password -------------------------------------------*/ + +read_password(k,prompt,verify) + C_Block *k; + char *prompt; + int verify; + +This routine issues the supplied prompt, turns off echo, if possible, and +reads an input string. If verify is non-zero, it does it again, for use +in applications such as changing a password. If verify is non-zero, both +versions are compared, and the input is requested repeatedly until they +match. Then, the input string is mapped into a valid DES key, internally +using the string_to_key routine. The newly created key is copied to the +area pointed to by parameter "k". + +No meaningful value is returned. If an error occurs trying to manipulate +the terminal echo, the routine forces the process to exit. + +/* get_line ------------------------*/ +long get_line(p,max) + char *p; + long max; + +Reads input characters from standard input until either a newline appears or +else the max length is reached. The characters read are stuffed into +the string pointed to, which will always be null terminated. The newline +is not inserted in the string. The max parameter includes the byte needed +for the null terminator, so allocate and pass one more than the maximum +string length desired. diff --git a/src/lib/crypto/builtin/des/f_aead.c b/src/lib/crypto/builtin/des/f_aead.c new file mode 100644 index 000000000000..71b8dff4d432 --- /dev/null +++ b/src/lib/crypto/builtin/des/f_aead.c @@ -0,0 +1,173 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2008 by the Massachusetts Institute of Technology. + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. 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 Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "crypto_int.h" +#include "des_int.h" +#include "f_tables.h" + +const mit_des_cblock mit_des_zeroblock /* = all zero */; + +void +krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + struct iov_cursor cursor; + unsigned char block[MIT_DES_BLOCK_LENGTH]; + + /* Get key pointer here. This won't need to be reinitialized. */ + kp = (const unsigned DES_INT32 *)schedule; + + /* Initialize left and right with the contents of the initial vector. */ + ip = (ivec != NULL) ? ivec : mit_des_zeroblock; + left = load_32_be(ip); + right = load_32_be(ip + 4); + + k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); + while (k5_iov_cursor_get(&cursor, block)) { + /* Decompose this block and xor it with the previous ciphertext. */ + left ^= load_32_be(block); + right ^= load_32_be(block + 4); + + /* Encrypt what we have and put back into block. */ + DES_DO_ENCRYPT(left, right, kp); + store_32_be(left, block); + store_32_be(right, block + 4); + + k5_iov_cursor_put(&cursor, block); + } + + if (ivec != NULL) { + store_32_be(left, ivec); + store_32_be(right, ivec + 4); + } +} + +void +krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + unsigned DES_INT32 ocipherl, ocipherr; + unsigned DES_INT32 cipherl, cipherr; + struct iov_cursor cursor; + unsigned char block[MIT_DES_BLOCK_LENGTH]; + + /* Get key pointer here. This won't need to be reinitialized. */ + kp = (const unsigned DES_INT32 *)schedule; + + /* + * Decrypting is harder than encrypting because of + * the necessity of remembering a lot more things. + * Should think about this a little more... + */ + + /* Prime the old cipher with ivec. */ + ip = (ivec != NULL) ? ivec : mit_des_zeroblock; + ocipherl = load_32_be(ip); + ocipherr = load_32_be(ip + 4); + + k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); + while (k5_iov_cursor_get(&cursor, block)) { + /* Split this block into left and right. */ + cipherl = left = load_32_be(block); + cipherr = right = load_32_be(block + 4); + + /* Decrypt and xor with the old cipher to get plain text. */ + DES_DO_DECRYPT(left, right, kp); + left ^= ocipherl; + right ^= ocipherr; + + /* Store the encrypted halves back into block. */ + store_32_be(left, block); + store_32_be(right, block + 4); + + /* Save current cipher block halves. */ + ocipherl = cipherl; + ocipherr = cipherr; + + k5_iov_cursor_put(&cursor, block); + } + + if (ivec != NULL) { + store_32_be(ocipherl, ivec); + store_32_be(ocipherr, ivec + 4); + } +} + +void +krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, mit_des_cblock ivec, + mit_des_cblock out) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + struct iov_cursor cursor; + unsigned char block[MIT_DES_BLOCK_LENGTH]; + + /* Get key pointer here. This won't need to be reinitialized. */ + kp = (const unsigned DES_INT32 *)schedule; + + /* Initialize left and right with the contents of the initial vector. */ + ip = (ivec != NULL) ? ivec : mit_des_zeroblock; + left = load_32_be(ip); + right = load_32_be(ip + 4); + + k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, TRUE); + while (k5_iov_cursor_get(&cursor, block)) { + /* Decompose this block and xor it with the previous ciphertext. */ + left ^= load_32_be(block); + right ^= load_32_be(block + 4); + + /* Encrypt what we have. */ + DES_DO_ENCRYPT(left, right, kp); + } + + /* Output the final ciphertext block. */ + store_32_be(left, out); + store_32_be(right, out + 4); +} + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) +void krb5int_des_do_encrypt_2 (unsigned DES_INT32 *left, + unsigned DES_INT32 *right, + const unsigned DES_INT32 *kp) +{ + DES_DO_ENCRYPT_1 (*left, *right, kp); +} + +void krb5int_des_do_decrypt_2 (unsigned DES_INT32 *left, + unsigned DES_INT32 *right, + const unsigned DES_INT32 *kp) +{ + DES_DO_DECRYPT_1 (*left, *right, kp); +} +#endif diff --git a/src/lib/crypto/builtin/des/f_cbc.c b/src/lib/crypto/builtin/des/f_cbc.c new file mode 100644 index 000000000000..84d5382f22f4 --- /dev/null +++ b/src/lib/crypto/builtin/des/f_cbc.c @@ -0,0 +1,256 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/f_cbc.c */ +/* + * Copyright (C) 1990 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. + */ + +/* + * CBC functions; used only by the test programs at this time. (krb5 uses the + * functions in f_aead.c instead.) + */ + +/* + * des_cbc_encrypt.c - an implementation of the DES cipher function in cbc mode + */ +#include "des_int.h" +#include "f_tables.h" + +/* + * des_cbc_encrypt - {en,de}crypt a stream in CBC mode + */ + +/* + * This routine performs DES cipher-block-chaining operation, either + * encrypting from cleartext to ciphertext, if encrypt != 0 or + * decrypting from ciphertext to cleartext, if encrypt == 0. + * + * The key schedule is passed as an arg, as well as the cleartext or + * ciphertext. The cleartext and ciphertext should be in host order. + * + * NOTE-- the output is ALWAYS an multiple of 8 bytes long. If not + * enough space was provided, your program will get trashed. + * + * For encryption, the cleartext string is null padded, at the end, to + * an integral multiple of eight bytes. + * + * For decryption, the ciphertext will be used in integral multiples + * of 8 bytes, but only the first "length" bytes returned into the + * cleartext. + */ + +const mit_des_cblock mit_des_zeroblock /* = all zero */; + +static void +des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, + unsigned long length, const mit_des_key_schedule schedule, + const mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + unsigned char *op; + + /* + * Get key pointer here. This won't need to be reinitialized + */ + kp = (const unsigned DES_INT32 *)schedule; + + /* + * Initialize left and right with the contents of the initial + * vector. + */ + ip = ivec; + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + + /* + * Suitably initialized, now work the length down 8 bytes + * at a time. + */ + ip = *in; + op = *out; + while (length > 0) { + /* + * Get more input, xor it in. If the length is + * greater than or equal to 8 this is straight + * forward. Otherwise we have to fart around. + */ + if (length >= 8) { + unsigned DES_INT32 temp; + GET_HALF_BLOCK(temp, ip); + left ^= temp; + GET_HALF_BLOCK(temp, ip); + right ^= temp; + length -= 8; + } else { + /* + * Oh, shoot. We need to pad the + * end with zeroes. Work backwards + * to do this. + */ + ip += (int) length; + switch(length) { + case 7: + right ^= (*(--ip) & FF_UINT32) << 8; + case 6: + right ^= (*(--ip) & FF_UINT32) << 16; + case 5: + right ^= (*(--ip) & FF_UINT32) << 24; + case 4: + left ^= *(--ip) & FF_UINT32; + case 3: + left ^= (*(--ip) & FF_UINT32) << 8; + case 2: + left ^= (*(--ip) & FF_UINT32) << 16; + case 1: + left ^= (*(--ip) & FF_UINT32) << 24; + break; + } + length = 0; + } + + /* + * Encrypt what we have + */ + DES_DO_ENCRYPT(left, right, kp); + + /* + * Copy the results out + */ + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + } +} + +static void +des_cbc_decrypt(const mit_des_cblock *in, mit_des_cblock *out, + unsigned long length, const mit_des_key_schedule schedule, + const mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + unsigned char *op; + unsigned DES_INT32 ocipherl, ocipherr; + unsigned DES_INT32 cipherl, cipherr; + + /* + * Get key pointer here. This won't need to be reinitialized + */ + kp = (const unsigned DES_INT32 *)schedule; + + /* + * Decrypting is harder than encrypting because of + * the necessity of remembering a lot more things. + * Should think about this a little more... + */ + + if (length <= 0) + return; + + /* + * Prime the old cipher with ivec. + */ + ip = ivec; + GET_HALF_BLOCK(ocipherl, ip); + GET_HALF_BLOCK(ocipherr, ip); + + /* + * Now do this in earnest until we run out of length. + */ + ip = *in; + op = *out; + for (;;) { /* check done inside loop */ + /* + * Read a block from the input into left and + * right. Save this cipher block for later. + */ + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + cipherl = left; + cipherr = right; + + /* + * Decrypt this. + */ + DES_DO_DECRYPT(left, right, kp); + + /* + * Xor with the old cipher to get plain + * text. Output 8 or less bytes of this. + */ + left ^= ocipherl; + right ^= ocipherr; + if (length > 8) { + length -= 8; + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + /* + * Save current cipher block here + */ + ocipherl = cipherl; + ocipherr = cipherr; + } else { + /* + * Trouble here. Start at end of output, + * work backwards. + */ + op += (int) length; + switch(length) { + case 8: + *(--op) = (unsigned char) (right & 0xff); + case 7: + *(--op) = (unsigned char) ((right >> 8) & 0xff); + case 6: + *(--op) = (unsigned char) ((right >> 16) & 0xff); + case 5: + *(--op) = (unsigned char) ((right >> 24) & 0xff); + case 4: + *(--op) = (unsigned char) (left & 0xff); + case 3: + *(--op) = (unsigned char) ((left >> 8) & 0xff); + case 2: + *(--op) = (unsigned char) ((left >> 16) & 0xff); + case 1: + *(--op) = (unsigned char) ((left >> 24) & 0xff); + break; + } + break; /* we're done */ + } + } +} + +int +mit_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, + unsigned long length, const mit_des_key_schedule schedule, + const mit_des_cblock ivec, int enc) +{ + /* + * Deal with encryption and decryption separately. + */ + if (enc) + des_cbc_encrypt(in, out, length, schedule, ivec); + else + des_cbc_decrypt(in, out, length, schedule, ivec); + return 0; +} diff --git a/src/lib/crypto/builtin/des/f_cksum.c b/src/lib/crypto/builtin/des/f_cksum.c new file mode 100644 index 000000000000..4492ce6df41b --- /dev/null +++ b/src/lib/crypto/builtin/des/f_cksum.c @@ -0,0 +1,136 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/f_cksum.c */ +/* + * Copyright (C) 1990 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. + */ + +/* DES implementation donated by Dennis Ferguson */ + +/* + * des_cbc_cksum.c - compute an 8 byte checksum using DES in CBC mode + */ +#include "des_int.h" +#include "f_tables.h" + +/* + * This routine performs DES cipher-block-chaining checksum operation, + * a.k.a. Message Authentication Code. It ALWAYS encrypts from input + * to a single 64 bit output MAC checksum. + * + * The key schedule is passed as an arg, as well as the cleartext or + * ciphertext. The cleartext and ciphertext should be in host order. + * + * NOTE-- the output is ALWAYS 8 bytes long. If not enough space was + * provided, your program will get trashed. + * + * The input is null padded, at the end (highest addr), to an integral + * multiple of eight bytes. + */ + +unsigned long +mit_des_cbc_cksum(const krb5_octet *in, krb5_octet *out, + unsigned long length, const mit_des_key_schedule schedule, + const krb5_octet *ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + unsigned char *op; + register DES_INT32 len; + + /* + * Initialize left and right with the contents of the initial + * vector. + */ + ip = ivec; + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + + /* + * Suitably initialized, now work the length down 8 bytes + * at a time. + */ + ip = in; + len = length; + while (len > 0) { + /* + * Get more input, xor it in. If the length is + * greater than or equal to 8 this is straight + * forward. Otherwise we have to fart around. + */ + if (len >= 8) { + unsigned DES_INT32 temp; + GET_HALF_BLOCK(temp, ip); + left ^= temp; + GET_HALF_BLOCK(temp, ip); + right ^= temp; + len -= 8; + } else { + /* + * Oh, shoot. We need to pad the + * end with zeroes. Work backwards + * to do this. + */ + ip += (int) len; + switch(len) { + case 7: + right ^= (*(--ip) & FF_UINT32) << 8; + case 6: + right ^= (*(--ip) & FF_UINT32) << 16; + case 5: + right ^= (*(--ip) & FF_UINT32) << 24; + case 4: + left ^= *(--ip) & FF_UINT32; + case 3: + left ^= (*(--ip) & FF_UINT32) << 8; + case 2: + left ^= (*(--ip) & FF_UINT32) << 16; + case 1: + left ^= (*(--ip) & FF_UINT32) << 24; + break; + } + len = 0; + } + + /* + * Encrypt what we have + */ + kp = (const unsigned DES_INT32 *)schedule; + DES_DO_ENCRYPT(left, right, kp); + } + + /* + * Done. Left and right have the checksum. Put it into + * the output. + */ + op = out; + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + + /* + * Return right. I'll bet the MIT code returns this + * inconsistantly (with the low order byte of the checksum + * not always in the low order byte of the DES_INT32). We won't. + */ + return right & 0xFFFFFFFFUL; +} diff --git a/src/lib/crypto/builtin/des/f_parity.c b/src/lib/crypto/builtin/des/f_parity.c new file mode 100644 index 000000000000..460b5061b5bc --- /dev/null +++ b/src/lib/crypto/builtin/des/f_parity.c @@ -0,0 +1,56 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * These routines check and fix parity of encryption keys for the DES + * algorithm. + * + * They are a replacement for routines in key_parity.c, that don't require + * the table building that they do. + * + * Mark Eichin -- Cygnus Support + */ + + +#include "des_int.h" + +/* + * des_fixup_key_parity: Forces odd parity per byte; parity is bits + * 8,16,...64 in des order, implies 0, 8, 16, ... + * vax order. + */ +#define smask(step) ((1<<step)-1) +#define pstep(x,step) (((x)&smask(step))^(((x)>>step)&smask(step))) +#define parity_char(x) pstep(pstep(pstep((x),4),2),1) + +void +mit_des_fixup_key_parity(mit_des_cblock key) +{ + unsigned int i; + for (i=0; i<sizeof(mit_des_cblock); i++) + { + key[i] &= 0xfe; + key[i] |= 1^parity_char(key[i]); + } + + return; +} + +/* + * des_check_key_parity: returns true iff key has the correct des parity. + * See des_fix_key_parity for the definition of + * correct des parity. + */ +int +mit_des_check_key_parity(mit_des_cblock key) +{ + unsigned int i; + + for (i=0; i<sizeof(mit_des_cblock); i++) + { + if((key[i] & 1) == parity_char(0xfe&key[i])) + { + return 0; + } + } + + return(1); +} diff --git a/src/lib/crypto/builtin/des/f_sched.c b/src/lib/crypto/builtin/des/f_sched.c new file mode 100644 index 000000000000..89d820f45957 --- /dev/null +++ b/src/lib/crypto/builtin/des/f_sched.c @@ -0,0 +1,359 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/f_sched.c */ +/* + * Copyright (C) 1990 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. + */ + +/* DES implementation donated by Dennis Ferguson */ + +/* + * des_make_sched.c - permute a DES key, returning the resulting key schedule + */ +#include "k5-int.h" +#include "des_int.h" + +/* + * Permuted choice 1 tables. These are used to extract bits + * from the left and right parts of the key to form Ci and Di. + * The code that uses these tables knows which bits from which + * part of each key are used to form Ci and Di. + */ +static const unsigned DES_INT32 PC1_CL[8] = { + 0x00000000, 0x00000010, 0x00001000, 0x00001010, + 0x00100000, 0x00100010, 0x00101000, 0x00101010 +}; + +static const unsigned DES_INT32 PC1_DL[16] = { + 0x00000000, 0x00100000, 0x00001000, 0x00101000, + 0x00000010, 0x00100010, 0x00001010, 0x00101010, + 0x00000001, 0x00100001, 0x00001001, 0x00101001, + 0x00000011, 0x00100011, 0x00001011, 0x00101011 +}; + +static const unsigned DES_INT32 PC1_CR[16] = { + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const unsigned DES_INT32 PC1_DR[8] = { + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100 +}; + + +/* + * At the start of some iterations of the key schedule we do + * a circular left shift by one place, while for others we do a shift by + * two places. This has bits set for the iterations where we do 2 bit + * shifts, starting at the low order bit. + */ +#define TWO_BIT_SHIFTS 0x7efc + +/* + * Permuted choice 2 tables. The first actually produces the low order + * 24 bits of the subkey Ki from the 28 bit value of Ci. The second produces + * the high order 24 bits from Di. The tables are indexed by six bit + * segments of Ci and Di respectively. The code is handcrafted to compute + * the appropriate 6 bit chunks. + * + * Note that for ease of computation, the 24 bit values are produced with + * six bits going into each byte. Note also that the table has been byte + * rearranged to produce keys which match the order we will apply them + * in in the des code. + */ +static const unsigned DES_INT32 PC2_C[4][64] = { + { + 0x00000000, 0x00000004, 0x00010000, 0x00010004, + 0x00000400, 0x00000404, 0x00010400, 0x00010404, + 0x00000020, 0x00000024, 0x00010020, 0x00010024, + 0x00000420, 0x00000424, 0x00010420, 0x00010424, + 0x01000000, 0x01000004, 0x01010000, 0x01010004, + 0x01000400, 0x01000404, 0x01010400, 0x01010404, + 0x01000020, 0x01000024, 0x01010020, 0x01010024, + 0x01000420, 0x01000424, 0x01010420, 0x01010424, + 0x00020000, 0x00020004, 0x00030000, 0x00030004, + 0x00020400, 0x00020404, 0x00030400, 0x00030404, + 0x00020020, 0x00020024, 0x00030020, 0x00030024, + 0x00020420, 0x00020424, 0x00030420, 0x00030424, + 0x01020000, 0x01020004, 0x01030000, 0x01030004, + 0x01020400, 0x01020404, 0x01030400, 0x01030404, + 0x01020020, 0x01020024, 0x01030020, 0x01030024, + 0x01020420, 0x01020424, 0x01030420, 0x01030424, + }, + { + 0x00000000, 0x02000000, 0x00000800, 0x02000800, + 0x00080000, 0x02080000, 0x00080800, 0x02080800, + 0x00000001, 0x02000001, 0x00000801, 0x02000801, + 0x00080001, 0x02080001, 0x00080801, 0x02080801, + 0x00000100, 0x02000100, 0x00000900, 0x02000900, + 0x00080100, 0x02080100, 0x00080900, 0x02080900, + 0x00000101, 0x02000101, 0x00000901, 0x02000901, + 0x00080101, 0x02080101, 0x00080901, 0x02080901, + 0x10000000, 0x12000000, 0x10000800, 0x12000800, + 0x10080000, 0x12080000, 0x10080800, 0x12080800, + 0x10000001, 0x12000001, 0x10000801, 0x12000801, + 0x10080001, 0x12080001, 0x10080801, 0x12080801, + 0x10000100, 0x12000100, 0x10000900, 0x12000900, + 0x10080100, 0x12080100, 0x10080900, 0x12080900, + 0x10000101, 0x12000101, 0x10000901, 0x12000901, + 0x10080101, 0x12080101, 0x10080901, 0x12080901, + }, + { + 0x00000000, 0x00040000, 0x00002000, 0x00042000, + 0x00100000, 0x00140000, 0x00102000, 0x00142000, + 0x20000000, 0x20040000, 0x20002000, 0x20042000, + 0x20100000, 0x20140000, 0x20102000, 0x20142000, + 0x00000008, 0x00040008, 0x00002008, 0x00042008, + 0x00100008, 0x00140008, 0x00102008, 0x00142008, + 0x20000008, 0x20040008, 0x20002008, 0x20042008, + 0x20100008, 0x20140008, 0x20102008, 0x20142008, + 0x00200000, 0x00240000, 0x00202000, 0x00242000, + 0x00300000, 0x00340000, 0x00302000, 0x00342000, + 0x20200000, 0x20240000, 0x20202000, 0x20242000, + 0x20300000, 0x20340000, 0x20302000, 0x20342000, + 0x00200008, 0x00240008, 0x00202008, 0x00242008, + 0x00300008, 0x00340008, 0x00302008, 0x00342008, + 0x20200008, 0x20240008, 0x20202008, 0x20242008, + 0x20300008, 0x20340008, 0x20302008, 0x20342008, + }, + { + 0x00000000, 0x00000010, 0x08000000, 0x08000010, + 0x00000200, 0x00000210, 0x08000200, 0x08000210, + 0x00000002, 0x00000012, 0x08000002, 0x08000012, + 0x00000202, 0x00000212, 0x08000202, 0x08000212, + 0x04000000, 0x04000010, 0x0c000000, 0x0c000010, + 0x04000200, 0x04000210, 0x0c000200, 0x0c000210, + 0x04000002, 0x04000012, 0x0c000002, 0x0c000012, + 0x04000202, 0x04000212, 0x0c000202, 0x0c000212, + 0x00001000, 0x00001010, 0x08001000, 0x08001010, + 0x00001200, 0x00001210, 0x08001200, 0x08001210, + 0x00001002, 0x00001012, 0x08001002, 0x08001012, + 0x00001202, 0x00001212, 0x08001202, 0x08001212, + 0x04001000, 0x04001010, 0x0c001000, 0x0c001010, + 0x04001200, 0x04001210, 0x0c001200, 0x0c001210, + 0x04001002, 0x04001012, 0x0c001002, 0x0c001012, + 0x04001202, 0x04001212, 0x0c001202, 0x0c001212 + }, +}; + +static const unsigned DES_INT32 PC2_D[4][64] = { + { + 0x00000000, 0x02000000, 0x00020000, 0x02020000, + 0x00000100, 0x02000100, 0x00020100, 0x02020100, + 0x00000008, 0x02000008, 0x00020008, 0x02020008, + 0x00000108, 0x02000108, 0x00020108, 0x02020108, + 0x00200000, 0x02200000, 0x00220000, 0x02220000, + 0x00200100, 0x02200100, 0x00220100, 0x02220100, + 0x00200008, 0x02200008, 0x00220008, 0x02220008, + 0x00200108, 0x02200108, 0x00220108, 0x02220108, + 0x00000200, 0x02000200, 0x00020200, 0x02020200, + 0x00000300, 0x02000300, 0x00020300, 0x02020300, + 0x00000208, 0x02000208, 0x00020208, 0x02020208, + 0x00000308, 0x02000308, 0x00020308, 0x02020308, + 0x00200200, 0x02200200, 0x00220200, 0x02220200, + 0x00200300, 0x02200300, 0x00220300, 0x02220300, + 0x00200208, 0x02200208, 0x00220208, 0x02220208, + 0x00200308, 0x02200308, 0x00220308, 0x02220308, + }, + { + 0x00000000, 0x00001000, 0x00000020, 0x00001020, + 0x00100000, 0x00101000, 0x00100020, 0x00101020, + 0x08000000, 0x08001000, 0x08000020, 0x08001020, + 0x08100000, 0x08101000, 0x08100020, 0x08101020, + 0x00000004, 0x00001004, 0x00000024, 0x00001024, + 0x00100004, 0x00101004, 0x00100024, 0x00101024, + 0x08000004, 0x08001004, 0x08000024, 0x08001024, + 0x08100004, 0x08101004, 0x08100024, 0x08101024, + 0x00000400, 0x00001400, 0x00000420, 0x00001420, + 0x00100400, 0x00101400, 0x00100420, 0x00101420, + 0x08000400, 0x08001400, 0x08000420, 0x08001420, + 0x08100400, 0x08101400, 0x08100420, 0x08101420, + 0x00000404, 0x00001404, 0x00000424, 0x00001424, + 0x00100404, 0x00101404, 0x00100424, 0x00101424, + 0x08000404, 0x08001404, 0x08000424, 0x08001424, + 0x08100404, 0x08101404, 0x08100424, 0x08101424, + }, + { + 0x00000000, 0x10000000, 0x00010000, 0x10010000, + 0x00000002, 0x10000002, 0x00010002, 0x10010002, + 0x00002000, 0x10002000, 0x00012000, 0x10012000, + 0x00002002, 0x10002002, 0x00012002, 0x10012002, + 0x00040000, 0x10040000, 0x00050000, 0x10050000, + 0x00040002, 0x10040002, 0x00050002, 0x10050002, + 0x00042000, 0x10042000, 0x00052000, 0x10052000, + 0x00042002, 0x10042002, 0x00052002, 0x10052002, + 0x20000000, 0x30000000, 0x20010000, 0x30010000, + 0x20000002, 0x30000002, 0x20010002, 0x30010002, + 0x20002000, 0x30002000, 0x20012000, 0x30012000, + 0x20002002, 0x30002002, 0x20012002, 0x30012002, + 0x20040000, 0x30040000, 0x20050000, 0x30050000, + 0x20040002, 0x30040002, 0x20050002, 0x30050002, + 0x20042000, 0x30042000, 0x20052000, 0x30052000, + 0x20042002, 0x30042002, 0x20052002, 0x30052002, + }, + { + 0x00000000, 0x04000000, 0x00000001, 0x04000001, + 0x01000000, 0x05000000, 0x01000001, 0x05000001, + 0x00000010, 0x04000010, 0x00000011, 0x04000011, + 0x01000010, 0x05000010, 0x01000011, 0x05000011, + 0x00080000, 0x04080000, 0x00080001, 0x04080001, + 0x01080000, 0x05080000, 0x01080001, 0x05080001, + 0x00080010, 0x04080010, 0x00080011, 0x04080011, + 0x01080010, 0x05080010, 0x01080011, 0x05080011, + 0x00000800, 0x04000800, 0x00000801, 0x04000801, + 0x01000800, 0x05000800, 0x01000801, 0x05000801, + 0x00000810, 0x04000810, 0x00000811, 0x04000811, + 0x01000810, 0x05000810, 0x01000811, 0x05000811, + 0x00080800, 0x04080800, 0x00080801, 0x04080801, + 0x01080800, 0x05080800, 0x01080801, 0x05080801, + 0x00080810, 0x04080810, 0x00080811, 0x04080811, + 0x01080810, 0x05080810, 0x01080811, 0x05080811 + }, +}; + + + +/* + * Permute the key to give us our key schedule. + */ +int +mit_des_make_key_sched(mit_des_cblock key, mit_des_key_schedule schedule) +{ + register unsigned DES_INT32 c, d; + + { + /* + * Need a pointer for the keys and a temporary DES_INT32 + */ + const unsigned char *k; + register unsigned DES_INT32 tmp; + + /* + * Fetch the key into something we can work with + */ + k = key; + + /* + * The first permutted choice gives us the 28 bits for C0 and + * 28 for D0. C0 gets 12 bits from the left key and 16 from + * the right, while D0 gets 16 from the left and 12 from the + * right. The code knows which bits go where. + */ + tmp = load_32_be(k), k += 4; + + c = PC1_CL[(tmp >> 29) & 0x7] + | (PC1_CL[(tmp >> 21) & 0x7] << 1) + | (PC1_CL[(tmp >> 13) & 0x7] << 2) + | (PC1_CL[(tmp >> 5) & 0x7] << 3); + d = PC1_DL[(tmp >> 25) & 0xf] + | (PC1_DL[(tmp >> 17) & 0xf] << 1) + | (PC1_DL[(tmp >> 9) & 0xf] << 2) + | (PC1_DL[(tmp >> 1) & 0xf] << 3); + + tmp = load_32_be(k), k += 4; + + c |= PC1_CR[(tmp >> 28) & 0xf] + | (PC1_CR[(tmp >> 20) & 0xf] << 1) + | (PC1_CR[(tmp >> 12) & 0xf] << 2) + | (PC1_CR[(tmp >> 4) & 0xf] << 3); + d |= PC1_DR[(tmp >> 25) & 0x7] + | (PC1_DR[(tmp >> 17) & 0x7] << 1) + | (PC1_DR[(tmp >> 9) & 0x7] << 2) + | (PC1_DR[(tmp >> 1) & 0x7] << 3); + } + + { + /* + * Need several temporaries in here + */ + register unsigned DES_INT32 ltmp, rtmp; + register unsigned DES_INT32 *k; + register int two_bit_shifts; + register int i; + /* + * Now iterate to compute the key schedule. Note that we + * record the entire set of subkeys in 6 bit chunks since + * they are used that way. At 6 bits/char, we need + * 48/6 char's/subkey * 16 subkeys/encryption == 128 bytes. + * The schedule must be this big. + */ + k = (unsigned DES_INT32 *)schedule; + two_bit_shifts = TWO_BIT_SHIFTS; + for (i = 16; i > 0; i--) { + /* + * Do the rotation. One bit and two bit rotations + * are done separately. Note C and D are 28 bits. + */ + if (two_bit_shifts & 0x1) { + c = ((c << 2) & 0xffffffc) | (c >> 26); + d = ((d << 2) & 0xffffffc) | (d >> 26); + } else { + c = ((c << 1) & 0xffffffe) | (c >> 27); + d = ((d << 1) & 0xffffffe) | (d >> 27); + } + two_bit_shifts >>= 1; + + /* + * Apply permutted choice 2 to C to get the first + * 24 bits worth of keys. Note that bits 9, 18, 22 + * and 25 (using DES numbering) in C are unused. The + * shift-mask stuff is done to delete these bits from + * the indices, since this cuts the table size in half. + * + * The table is torqued, by the way. If the standard + * byte order for this (high to low order) is 1234, + * the table actually gives us 4132. + */ + ltmp = PC2_C[0][((c >> 22) & 0x3f)] + | PC2_C[1][((c >> 15) & 0xf) | ((c >> 16) & 0x30)] + | PC2_C[2][((c >> 4) & 0x3) | ((c >> 9) & 0x3c)] + | PC2_C[3][((c ) & 0x7) | ((c >> 4) & 0x38)]; + /* + * Apply permutted choice 2 to D to get the other half. + * Here, bits 7, 10, 15 and 26 go unused. The sqeezing + * actually turns out to be cheaper here. + * + * This table is similarly torqued. If the standard + * byte order is 5678, the table has the bytes permuted + * to give us 7685. + */ + rtmp = PC2_D[0][((d >> 22) & 0x3f)] + | PC2_D[1][((d >> 14) & 0xf) | ((d >> 15) & 0x30)] + | PC2_D[2][((d >> 7) & 0x3f)] + | PC2_D[3][((d ) & 0x3) | ((d >> 1) & 0x3c)]; + + /* + * Make up two words of the key schedule, with a + * byte order which is convenient for the DES + * inner loop. The high order (first) word will + * hold bytes 7135 (high to low order) while the + * second holds bytes 4682. + */ + *k++ = (ltmp & 0x00ffff00) | (rtmp & 0xff0000ff); + *k++ = (ltmp & 0xff0000ff) | (rtmp & 0x00ffff00); + } + } + return (0); +} diff --git a/src/lib/crypto/builtin/des/f_tables.c b/src/lib/crypto/builtin/des/f_tables.c new file mode 100644 index 000000000000..6308cb0d5cf1 --- /dev/null +++ b/src/lib/crypto/builtin/des/f_tables.c @@ -0,0 +1,370 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/f_tables.c */ +/* + * Copyright (C) 1990 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. + */ + +/* DES implementation donated by Dennis Ferguson */ + +/* + * des_tables.c - precomputed tables used for the DES cipher function + */ + +/* + * Include the header file so something will complain if the + * declarations get out of sync + */ +#include "des_int.h" +#include "f_tables.h" + +/* + * These tables may be declared const if you want. Many compilers + * don't support this, though. + */ + +/* + * The DES algorithm which uses these is intended to be fairly speedy + * at the expense of some memory. All the standard hacks are used. + * The S boxes and the P permutation are precomputed into one table. + * The E box never actually appears explicitly since it is easy to apply + * this algorithmically as needed. The initial permutation and final + * (inverse initial) permutation are computed from tables designed to + * permute one byte at a time. This should run pretty fast on machines + * with 32 bit words and bit field/multiple bit shift instructions which + * are fast. + */ + +/* + * The initial permutation array. This is used to compute both the + * left and the right halves of the initial permutation using bytes + * from words made from the following operations: + * + * ((left & 0x55555555) << 1) | (right & 0x55555555) for left half + * (left & 0xaaaaaaaa) | ((right & 0xaaaaaaaa) >> 1) for right half + * + * The scheme is that we index into the table using each byte. The + * result from the high order byte is or'd with the result from the + * next byte shifted left once is or'd with the result from the next + * byte shifted left twice if or'd with the result from the low order + * byte shifted left by three. Clear? + */ + +const unsigned DES_INT32 des_IP_table[256] = { + 0x00000000, 0x00000010, 0x00000001, 0x00000011, + 0x00001000, 0x00001010, 0x00001001, 0x00001011, + 0x00000100, 0x00000110, 0x00000101, 0x00000111, + 0x00001100, 0x00001110, 0x00001101, 0x00001111, + 0x00100000, 0x00100010, 0x00100001, 0x00100011, + 0x00101000, 0x00101010, 0x00101001, 0x00101011, + 0x00100100, 0x00100110, 0x00100101, 0x00100111, + 0x00101100, 0x00101110, 0x00101101, 0x00101111, + 0x00010000, 0x00010010, 0x00010001, 0x00010011, + 0x00011000, 0x00011010, 0x00011001, 0x00011011, + 0x00010100, 0x00010110, 0x00010101, 0x00010111, + 0x00011100, 0x00011110, 0x00011101, 0x00011111, + 0x00110000, 0x00110010, 0x00110001, 0x00110011, + 0x00111000, 0x00111010, 0x00111001, 0x00111011, + 0x00110100, 0x00110110, 0x00110101, 0x00110111, + 0x00111100, 0x00111110, 0x00111101, 0x00111111, + 0x10000000, 0x10000010, 0x10000001, 0x10000011, + 0x10001000, 0x10001010, 0x10001001, 0x10001011, + 0x10000100, 0x10000110, 0x10000101, 0x10000111, + 0x10001100, 0x10001110, 0x10001101, 0x10001111, + 0x10100000, 0x10100010, 0x10100001, 0x10100011, + 0x10101000, 0x10101010, 0x10101001, 0x10101011, + 0x10100100, 0x10100110, 0x10100101, 0x10100111, + 0x10101100, 0x10101110, 0x10101101, 0x10101111, + 0x10010000, 0x10010010, 0x10010001, 0x10010011, + 0x10011000, 0x10011010, 0x10011001, 0x10011011, + 0x10010100, 0x10010110, 0x10010101, 0x10010111, + 0x10011100, 0x10011110, 0x10011101, 0x10011111, + 0x10110000, 0x10110010, 0x10110001, 0x10110011, + 0x10111000, 0x10111010, 0x10111001, 0x10111011, + 0x10110100, 0x10110110, 0x10110101, 0x10110111, + 0x10111100, 0x10111110, 0x10111101, 0x10111111, + 0x01000000, 0x01000010, 0x01000001, 0x01000011, + 0x01001000, 0x01001010, 0x01001001, 0x01001011, + 0x01000100, 0x01000110, 0x01000101, 0x01000111, + 0x01001100, 0x01001110, 0x01001101, 0x01001111, + 0x01100000, 0x01100010, 0x01100001, 0x01100011, + 0x01101000, 0x01101010, 0x01101001, 0x01101011, + 0x01100100, 0x01100110, 0x01100101, 0x01100111, + 0x01101100, 0x01101110, 0x01101101, 0x01101111, + 0x01010000, 0x01010010, 0x01010001, 0x01010011, + 0x01011000, 0x01011010, 0x01011001, 0x01011011, + 0x01010100, 0x01010110, 0x01010101, 0x01010111, + 0x01011100, 0x01011110, 0x01011101, 0x01011111, + 0x01110000, 0x01110010, 0x01110001, 0x01110011, + 0x01111000, 0x01111010, 0x01111001, 0x01111011, + 0x01110100, 0x01110110, 0x01110101, 0x01110111, + 0x01111100, 0x01111110, 0x01111101, 0x01111111, + 0x11000000, 0x11000010, 0x11000001, 0x11000011, + 0x11001000, 0x11001010, 0x11001001, 0x11001011, + 0x11000100, 0x11000110, 0x11000101, 0x11000111, + 0x11001100, 0x11001110, 0x11001101, 0x11001111, + 0x11100000, 0x11100010, 0x11100001, 0x11100011, + 0x11101000, 0x11101010, 0x11101001, 0x11101011, + 0x11100100, 0x11100110, 0x11100101, 0x11100111, + 0x11101100, 0x11101110, 0x11101101, 0x11101111, + 0x11010000, 0x11010010, 0x11010001, 0x11010011, + 0x11011000, 0x11011010, 0x11011001, 0x11011011, + 0x11010100, 0x11010110, 0x11010101, 0x11010111, + 0x11011100, 0x11011110, 0x11011101, 0x11011111, + 0x11110000, 0x11110010, 0x11110001, 0x11110011, + 0x11111000, 0x11111010, 0x11111001, 0x11111011, + 0x11110100, 0x11110110, 0x11110101, 0x11110111, + 0x11111100, 0x11111110, 0x11111101, 0x11111111 +}; + +/* + * The final permutation array. Like the IP array, used + * to compute both the left and right results from the bytes + * of words computed from: + * + * ((left & 0x0f0f0f0f) << 4) | (right & 0x0f0f0f0f) for left result + * (left & 0xf0f0f0f0) | ((right & 0xf0f0f0f0) >> 4) for right result + * + * The result from the high order byte is shifted left 6 bits and + * or'd with the result from the next byte shifted left 4 bits, which + * is or'd with the result from the next byte shifted left 2 bits, + * which is or'd with the result from the low byte. + */ +const unsigned DES_INT32 des_FP_table[256] = { + 0x00000000, 0x02000000, 0x00020000, 0x02020000, + 0x00000200, 0x02000200, 0x00020200, 0x02020200, + 0x00000002, 0x02000002, 0x00020002, 0x02020002, + 0x00000202, 0x02000202, 0x00020202, 0x02020202, + 0x01000000, 0x03000000, 0x01020000, 0x03020000, + 0x01000200, 0x03000200, 0x01020200, 0x03020200, + 0x01000002, 0x03000002, 0x01020002, 0x03020002, + 0x01000202, 0x03000202, 0x01020202, 0x03020202, + 0x00010000, 0x02010000, 0x00030000, 0x02030000, + 0x00010200, 0x02010200, 0x00030200, 0x02030200, + 0x00010002, 0x02010002, 0x00030002, 0x02030002, + 0x00010202, 0x02010202, 0x00030202, 0x02030202, + 0x01010000, 0x03010000, 0x01030000, 0x03030000, + 0x01010200, 0x03010200, 0x01030200, 0x03030200, + 0x01010002, 0x03010002, 0x01030002, 0x03030002, + 0x01010202, 0x03010202, 0x01030202, 0x03030202, + 0x00000100, 0x02000100, 0x00020100, 0x02020100, + 0x00000300, 0x02000300, 0x00020300, 0x02020300, + 0x00000102, 0x02000102, 0x00020102, 0x02020102, + 0x00000302, 0x02000302, 0x00020302, 0x02020302, + 0x01000100, 0x03000100, 0x01020100, 0x03020100, + 0x01000300, 0x03000300, 0x01020300, 0x03020300, + 0x01000102, 0x03000102, 0x01020102, 0x03020102, + 0x01000302, 0x03000302, 0x01020302, 0x03020302, + 0x00010100, 0x02010100, 0x00030100, 0x02030100, + 0x00010300, 0x02010300, 0x00030300, 0x02030300, + 0x00010102, 0x02010102, 0x00030102, 0x02030102, + 0x00010302, 0x02010302, 0x00030302, 0x02030302, + 0x01010100, 0x03010100, 0x01030100, 0x03030100, + 0x01010300, 0x03010300, 0x01030300, 0x03030300, + 0x01010102, 0x03010102, 0x01030102, 0x03030102, + 0x01010302, 0x03010302, 0x01030302, 0x03030302, + 0x00000001, 0x02000001, 0x00020001, 0x02020001, + 0x00000201, 0x02000201, 0x00020201, 0x02020201, + 0x00000003, 0x02000003, 0x00020003, 0x02020003, + 0x00000203, 0x02000203, 0x00020203, 0x02020203, + 0x01000001, 0x03000001, 0x01020001, 0x03020001, + 0x01000201, 0x03000201, 0x01020201, 0x03020201, + 0x01000003, 0x03000003, 0x01020003, 0x03020003, + 0x01000203, 0x03000203, 0x01020203, 0x03020203, + 0x00010001, 0x02010001, 0x00030001, 0x02030001, + 0x00010201, 0x02010201, 0x00030201, 0x02030201, + 0x00010003, 0x02010003, 0x00030003, 0x02030003, + 0x00010203, 0x02010203, 0x00030203, 0x02030203, + 0x01010001, 0x03010001, 0x01030001, 0x03030001, + 0x01010201, 0x03010201, 0x01030201, 0x03030201, + 0x01010003, 0x03010003, 0x01030003, 0x03030003, + 0x01010203, 0x03010203, 0x01030203, 0x03030203, + 0x00000101, 0x02000101, 0x00020101, 0x02020101, + 0x00000301, 0x02000301, 0x00020301, 0x02020301, + 0x00000103, 0x02000103, 0x00020103, 0x02020103, + 0x00000303, 0x02000303, 0x00020303, 0x02020303, + 0x01000101, 0x03000101, 0x01020101, 0x03020101, + 0x01000301, 0x03000301, 0x01020301, 0x03020301, + 0x01000103, 0x03000103, 0x01020103, 0x03020103, + 0x01000303, 0x03000303, 0x01020303, 0x03020303, + 0x00010101, 0x02010101, 0x00030101, 0x02030101, + 0x00010301, 0x02010301, 0x00030301, 0x02030301, + 0x00010103, 0x02010103, 0x00030103, 0x02030103, + 0x00010303, 0x02010303, 0x00030303, 0x02030303, + 0x01010101, 0x03010101, 0x01030101, 0x03030101, + 0x01010301, 0x03010301, 0x01030301, 0x03030301, + 0x01010103, 0x03010103, 0x01030103, 0x03030103, + 0x01010303, 0x03010303, 0x01030303, 0x03030303 +}; + + +/* + * The SP table is actually the S boxes and the P permutation + * table combined. This table is actually reordered from the + * spec, to match the order of key application we follow. + */ +const unsigned DES_INT32 des_SP_table[8][64] = { + { + 0x00100000, 0x02100001, 0x02000401, 0x00000000, /* 7 */ + 0x00000400, 0x02000401, 0x00100401, 0x02100400, + 0x02100401, 0x00100000, 0x00000000, 0x02000001, + 0x00000001, 0x02000000, 0x02100001, 0x00000401, + 0x02000400, 0x00100401, 0x00100001, 0x02000400, + 0x02000001, 0x02100000, 0x02100400, 0x00100001, + 0x02100000, 0x00000400, 0x00000401, 0x02100401, + 0x00100400, 0x00000001, 0x02000000, 0x00100400, + 0x02000000, 0x00100400, 0x00100000, 0x02000401, + 0x02000401, 0x02100001, 0x02100001, 0x00000001, + 0x00100001, 0x02000000, 0x02000400, 0x00100000, + 0x02100400, 0x00000401, 0x00100401, 0x02100400, + 0x00000401, 0x02000001, 0x02100401, 0x02100000, + 0x00100400, 0x00000000, 0x00000001, 0x02100401, + 0x00000000, 0x00100401, 0x02100000, 0x00000400, + 0x02000001, 0x02000400, 0x00000400, 0x00100001, + }, + { + 0x00808200, 0x00000000, 0x00008000, 0x00808202, /* 1 */ + 0x00808002, 0x00008202, 0x00000002, 0x00008000, + 0x00000200, 0x00808200, 0x00808202, 0x00000200, + 0x00800202, 0x00808002, 0x00800000, 0x00000002, + 0x00000202, 0x00800200, 0x00800200, 0x00008200, + 0x00008200, 0x00808000, 0x00808000, 0x00800202, + 0x00008002, 0x00800002, 0x00800002, 0x00008002, + 0x00000000, 0x00000202, 0x00008202, 0x00800000, + 0x00008000, 0x00808202, 0x00000002, 0x00808000, + 0x00808200, 0x00800000, 0x00800000, 0x00000200, + 0x00808002, 0x00008000, 0x00008200, 0x00800002, + 0x00000200, 0x00000002, 0x00800202, 0x00008202, + 0x00808202, 0x00008002, 0x00808000, 0x00800202, + 0x00800002, 0x00000202, 0x00008202, 0x00808200, + 0x00000202, 0x00800200, 0x00800200, 0x00000000, + 0x00008002, 0x00008200, 0x00000000, 0x00808002, + }, + { + 0x00000104, 0x04010100, 0x00000000, 0x04010004, /* 3 */ + 0x04000100, 0x00000000, 0x00010104, 0x04000100, + 0x00010004, 0x04000004, 0x04000004, 0x00010000, + 0x04010104, 0x00010004, 0x04010000, 0x00000104, + 0x04000000, 0x00000004, 0x04010100, 0x00000100, + 0x00010100, 0x04010000, 0x04010004, 0x00010104, + 0x04000104, 0x00010100, 0x00010000, 0x04000104, + 0x00000004, 0x04010104, 0x00000100, 0x04000000, + 0x04010100, 0x04000000, 0x00010004, 0x00000104, + 0x00010000, 0x04010100, 0x04000100, 0x00000000, + 0x00000100, 0x00010004, 0x04010104, 0x04000100, + 0x04000004, 0x00000100, 0x00000000, 0x04010004, + 0x04000104, 0x00010000, 0x04000000, 0x04010104, + 0x00000004, 0x00010104, 0x00010100, 0x04000004, + 0x04010000, 0x04000104, 0x00000104, 0x04010000, + 0x00010104, 0x00000004, 0x04010004, 0x00010100, + }, + { + 0x00000080, 0x01040080, 0x01040000, 0x21000080, /* 5 */ + 0x00040000, 0x00000080, 0x20000000, 0x01040000, + 0x20040080, 0x00040000, 0x01000080, 0x20040080, + 0x21000080, 0x21040000, 0x00040080, 0x20000000, + 0x01000000, 0x20040000, 0x20040000, 0x00000000, + 0x20000080, 0x21040080, 0x21040080, 0x01000080, + 0x21040000, 0x20000080, 0x00000000, 0x21000000, + 0x01040080, 0x01000000, 0x21000000, 0x00040080, + 0x00040000, 0x21000080, 0x00000080, 0x01000000, + 0x20000000, 0x01040000, 0x21000080, 0x20040080, + 0x01000080, 0x20000000, 0x21040000, 0x01040080, + 0x20040080, 0x00000080, 0x01000000, 0x21040000, + 0x21040080, 0x00040080, 0x21000000, 0x21040080, + 0x01040000, 0x00000000, 0x20040000, 0x21000000, + 0x00040080, 0x01000080, 0x20000080, 0x00040000, + 0x00000000, 0x20040000, 0x01040080, 0x20000080, + }, + { + 0x80401000, 0x80001040, 0x80001040, 0x00000040, /* 4 */ + 0x00401040, 0x80400040, 0x80400000, 0x80001000, + 0x00000000, 0x00401000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00400040, 0x80400000, + 0x80000000, 0x00001000, 0x00400000, 0x80401000, + 0x00000040, 0x00400000, 0x80001000, 0x00001040, + 0x80400040, 0x80000000, 0x00001040, 0x00400040, + 0x00001000, 0x00401040, 0x80401040, 0x80000040, + 0x00400040, 0x80400000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00000000, 0x00401000, + 0x00001040, 0x00400040, 0x80400040, 0x80000000, + 0x80401000, 0x80001040, 0x80001040, 0x00000040, + 0x80401040, 0x80000040, 0x80000000, 0x00001000, + 0x80400000, 0x80001000, 0x00401040, 0x80400040, + 0x80001000, 0x00001040, 0x00400000, 0x80401000, + 0x00000040, 0x00400000, 0x00001000, 0x00401040, + }, + { + 0x10000008, 0x10200000, 0x00002000, 0x10202008, /* 6 */ + 0x10200000, 0x00000008, 0x10202008, 0x00200000, + 0x10002000, 0x00202008, 0x00200000, 0x10000008, + 0x00200008, 0x10002000, 0x10000000, 0x00002008, + 0x00000000, 0x00200008, 0x10002008, 0x00002000, + 0x00202000, 0x10002008, 0x00000008, 0x10200008, + 0x10200008, 0x00000000, 0x00202008, 0x10202000, + 0x00002008, 0x00202000, 0x10202000, 0x10000000, + 0x10002000, 0x00000008, 0x10200008, 0x00202000, + 0x10202008, 0x00200000, 0x00002008, 0x10000008, + 0x00200000, 0x10002000, 0x10000000, 0x00002008, + 0x10000008, 0x10202008, 0x00202000, 0x10200000, + 0x00202008, 0x10202000, 0x00000000, 0x10200008, + 0x00000008, 0x00002000, 0x10200000, 0x00202008, + 0x00002000, 0x00200008, 0x10002008, 0x00000000, + 0x10202000, 0x10000000, 0x00200008, 0x10002008, + }, + { + 0x08000820, 0x00000800, 0x00020000, 0x08020820, /* 8 */ + 0x08000000, 0x08000820, 0x00000020, 0x08000000, + 0x00020020, 0x08020000, 0x08020820, 0x00020800, + 0x08020800, 0x00020820, 0x00000800, 0x00000020, + 0x08020000, 0x08000020, 0x08000800, 0x00000820, + 0x00020800, 0x00020020, 0x08020020, 0x08020800, + 0x00000820, 0x00000000, 0x00000000, 0x08020020, + 0x08000020, 0x08000800, 0x00020820, 0x00020000, + 0x00020820, 0x00020000, 0x08020800, 0x00000800, + 0x00000020, 0x08020020, 0x00000800, 0x00020820, + 0x08000800, 0x00000020, 0x08000020, 0x08020000, + 0x08020020, 0x08000000, 0x00020000, 0x08000820, + 0x00000000, 0x08020820, 0x00020020, 0x08000020, + 0x08020000, 0x08000800, 0x08000820, 0x00000000, + 0x08020820, 0x00020800, 0x00020800, 0x00000820, + 0x00000820, 0x00020020, 0x08000000, 0x08020800, + }, + { + 0x40084010, 0x40004000, 0x00004000, 0x00084010, /* 2 */ + 0x00080000, 0x00000010, 0x40080010, 0x40004010, + 0x40000010, 0x40084010, 0x40084000, 0x40000000, + 0x40004000, 0x00080000, 0x00000010, 0x40080010, + 0x00084000, 0x00080010, 0x40004010, 0x00000000, + 0x40000000, 0x00004000, 0x00084010, 0x40080000, + 0x00080010, 0x40000010, 0x00000000, 0x00084000, + 0x00004010, 0x40084000, 0x40080000, 0x00004010, + 0x00000000, 0x00084010, 0x40080010, 0x00080000, + 0x40004010, 0x40080000, 0x40084000, 0x00004000, + 0x40080000, 0x40004000, 0x00000010, 0x40084010, + 0x00084010, 0x00000010, 0x00004000, 0x40000000, + 0x00004010, 0x40084000, 0x00080000, 0x40000010, + 0x00080010, 0x40004010, 0x40000010, 0x00080010, + 0x00084000, 0x00000000, 0x40004000, 0x00004010, + 0x40000000, 0x40080010, 0x40084010, 0x00084000 + }, +}; diff --git a/src/lib/crypto/builtin/des/f_tables.h b/src/lib/crypto/builtin/des/f_tables.h new file mode 100644 index 000000000000..a99eb0a14c6a --- /dev/null +++ b/src/lib/crypto/builtin/des/f_tables.h @@ -0,0 +1,285 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/f_tables.h */ +/* + * Copyright (C) 1990 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. + */ + +/* + * DES implementation donated by Dennis Ferguson + */ + +/* + * des_tables.h - declarations to import the DES tables, used internally + * by some of the library routines. + */ +#ifndef __DES_TABLES_H__ +#define __DES_TABLES_H__ /* nothing */ + +#include "k5-platform.h" +/* + * These may be declared const if you wish. Be sure to change the + * declarations in des_tables.c as well. + */ +extern const unsigned DES_INT32 des_IP_table[256]; +extern const unsigned DES_INT32 des_FP_table[256]; +extern const unsigned DES_INT32 des_SP_table[8][64]; + +/* + * Use standard shortforms to reference these to save typing + */ +#define IP des_IP_table +#define FP des_FP_table +#define SP des_SP_table + +#ifdef DEBUG +#define DEB(foofraw) printf foofraw +#else +#define DEB(foofraw) /* nothing */ +#endif + +/* + * Code to do a DES round using the tables. Note that the E expansion + * is easy to compute algorithmically, especially if done out-of-order. + * Take a look at its form and compare it to everything involving temp + * below. Since SP[0-7] don't have any bits in common set it is okay + * to do the successive xor's. + * + * Note too that the SP table has been reordered to match the order of + * the keys (if the original order of SP was 12345678, the reordered + * table is 71354682). This is unnecessary, but was done since some + * compilers seem to like you going through the matrix from beginning + * to end. + * + * There is a difference in the best way to do this depending on whether + * one is encrypting or decrypting. If encrypting we move forward through + * the keys and hence should move forward through the table. If decrypting + * we go back. Part of the need for this comes from trying to emulate + * existing software which generates a single key schedule and uses it + * both for encrypting and decrypting. Generating separate encryption + * and decryption key schedules would allow one to use the same code + * for both. + * + * left, right and temp should be unsigned DES_INT32 values. left and right + * should be the high and low order parts of the cipher block at the + * current stage of processing (this makes sense if you read the spec). + * kp should be an unsigned DES_INT32 pointer which points at the current + * set of subkeys in the key schedule. It is advanced to the next set + * (i.e. by 8 bytes) when this is done. + * + * This occurs in the innermost loop of the DES function. The four + * variables should really be in registers. + * + * When using this, the inner loop of the DES function might look like: + * + * for (i = 0; i < 8; i++) { + * DES_SP_{EN,DE}CRYPT_ROUND(left, right, temp, kp); + * DES_SP_{EN,DE}CRYPT_ROUND(right, left, temp, kp); + * } + * + * Note the trick above. You are supposed to do 16 rounds, swapping + * left and right at the end of each round. By doing two rounds at + * a time and swapping left and right in the code we can avoid the + * swaps altogether. + */ +#define DES_SP_ENCRYPT_ROUND(left, right, temp, kp) do { \ + (temp) = (((right) >> 11) | ((right) << 21)) ^ *(kp)++; \ + (left) ^= SP[0][((temp) >> 24) & 0x3f] \ + | SP[1][((temp) >> 16) & 0x3f] \ + | SP[2][((temp) >> 8) & 0x3f] \ + | SP[3][((temp) ) & 0x3f]; \ + (temp) = (((right) >> 23) | ((right) << 9)) ^ *(kp)++; \ + (left) ^= SP[4][((temp) >> 24) & 0x3f] \ + | SP[5][((temp) >> 16) & 0x3f] \ + | SP[6][((temp) >> 8) & 0x3f] \ + | SP[7][((temp) ) & 0x3f]; \ + } while(0); + +#define DES_SP_DECRYPT_ROUND(left, right, temp, kp) do { \ + (temp) = (((right) >> 23) | ((right) << 9)) ^ *(--(kp)); \ + (left) ^= SP[7][((temp) ) & 0x3f] \ + | SP[6][((temp) >> 8) & 0x3f] \ + | SP[5][((temp) >> 16) & 0x3f] \ + | SP[4][((temp) >> 24) & 0x3f]; \ + (temp) = (((right) >> 11) | ((right) << 21)) ^ *(--(kp)); \ + (left) ^= SP[3][((temp) ) & 0x3f] \ + | SP[2][((temp) >> 8) & 0x3f] \ + | SP[1][((temp) >> 16) & 0x3f] \ + | SP[0][((temp) >> 24) & 0x3f]; \ + } while (0); + +/* + * Macros to help deal with the initial permutation table. Note + * the IP table only deals with 32 bits at a time, allowing us to + * collect the bits we need to deal with each half into an unsigned + * DES_INT32. By carefully selecting how the bits are ordered we also + * take advantages of symmetries in the table so that we can use a + * single table to compute the permutation of all bytes. This sounds + * complicated, but if you go through the process of designing the + * table you'll find the symmetries fall right out. + * + * The follow macros compute the set of bits used to index the + * table for produce the left and right permuted result. + * + * The inserted cast to unsigned DES_INT32 circumvents a bug in + * the Macintosh MPW 3.2 C compiler which loses the unsignedness and + * propagates the high-order bit in the shift. + */ +#define DES_IP_LEFT_BITS(left, right) \ + ((((left) & 0x55555555) << 1) | ((right) & 0x55555555)) +#define DES_IP_RIGHT_BITS(left, right) \ + (((left) & 0xaaaaaaaa) | \ + ( ( (unsigned DES_INT32) ((right) & 0xaaaaaaaa) ) >> 1)) + +/* + * The following macro does an in-place initial permutation given + * the current left and right parts of the block and a single + * temporary. Use this more as a guide for rolling your own, though. + * The best way to do the IP depends on the form of the data you + * are dealing with. If you use this, though, try to make left, + * right and temp register unsigned DES_INT32s. + */ +#define DES_INITIAL_PERM(left, right, temp) do { \ + (temp) = DES_IP_RIGHT_BITS((left), (right)); \ + (right) = DES_IP_LEFT_BITS((left), (right)); \ + (left) = IP[((right) >> 24) & 0xff] \ + | (IP[((right) >> 16) & 0xff] << 1) \ + | (IP[((right) >> 8) & 0xff] << 2) \ + | (IP[(right) & 0xff] << 3); \ + (right) = IP[((temp) >> 24) & 0xff] \ + | (IP[((temp) >> 16) & 0xff] << 1) \ + | (IP[((temp) >> 8) & 0xff] << 2) \ + | (IP[(temp) & 0xff] << 3); \ + } while(0); + +/* + * Now the final permutation stuff. The same comments apply to + * this as to the initial permutation, except that we use different + * bits and shifts. + * + * The inserted cast to unsigned DES_INT32 circumvents a bug in + * the Macintosh MPW 3.2 C compiler which loses the unsignedness and + * propagates the high-order bit in the shift. + */ +#define DES_FP_LEFT_BITS(left, right) \ + ((((left) & 0x0f0f0f0f) << 4) | ((right) & 0x0f0f0f0f)) +#define DES_FP_RIGHT_BITS(left, right) \ + (((left) & 0xf0f0f0f0) | \ + ( ( (unsigned DES_INT32) ((right) & 0xf0f0f0f0) ) >> 4)) + + +/* + * Here is a sample final permutation. Note that there is a trick + * here. DES requires swapping the left and right parts after the + * last cipher round but before the final permutation. We do this + * swapping internally, which is why left and right are confused + * at the beginning. + */ +#define DES_FINAL_PERM(left, right, temp) do { \ + (temp) = DES_FP_RIGHT_BITS((right), (left)); \ + (right) = DES_FP_LEFT_BITS((right), (left)); \ + (left) = (FP[((right) >> 24) & 0xff] << 6) \ + | (FP[((right) >> 16) & 0xff] << 4) \ + | (FP[((right) >> 8) & 0xff] << 2) \ + | FP[(right) & 0xff]; \ + (right) = (FP[((temp) >> 24) & 0xff] << 6) \ + | (FP[((temp) >> 16) & 0xff] << 4) \ + | (FP[((temp) >> 8) & 0xff] << 2) \ + | FP[temp & 0xff]; \ + } while(0); + + +/* + * Finally, as a sample of how all this might be held together, the + * following two macros do in-place encryptions and decryptions. left + * and right are two unsigned DES_INT32 variables which at the beginning + * are expected to hold the clear (encrypted) block in host byte order + * (left the high order four bytes, right the low order). At the end + * they will contain the encrypted (clear) block. temp is an unsigned DES_INT32 + * used as a temporary. kp is an unsigned DES_INT32 pointer pointing at + * the start of the key schedule. All these should be in registers. + * + * You can probably do better than these by rewriting for particular + * situations. These aren't bad, though. + * + * The DEB macros enable debugging when this code breaks (typically + * when a buggy compiler breaks it), by printing the intermediate values + * at each stage of the encryption, so that by comparing the output to + * a known good machine, the location of the first error can be found. + */ +#define DES_DO_ENCRYPT_1(left, right, kp) \ + do { \ + register int i; \ + register unsigned DES_INT32 temp1; \ + DEB (("do_encrypt %8lX %8lX \n", left, right)); \ + DES_INITIAL_PERM((left), (right), (temp1)); \ + DEB ((" after IP %8lX %8lX\n", left, right)); \ + for (i = 0; i < 8; i++) { \ + DES_SP_ENCRYPT_ROUND((left), (right), (temp1), (kp)); \ + DEB ((" round %2d %8lX %8lX \n", i*2, left, right)); \ + DES_SP_ENCRYPT_ROUND((right), (left), (temp1), (kp)); \ + DEB ((" round %2d %8lX %8lX \n", 1+i*2, left, right)); \ + } \ + DES_FINAL_PERM((left), (right), (temp1)); \ + (kp) -= (2 * 16); \ + DEB ((" after FP %8lX %8lX \n", left, right)); \ + } while (0) + +#define DES_DO_DECRYPT_1(left, right, kp) \ + do { \ + register int i; \ + register unsigned DES_INT32 temp2; \ + DES_INITIAL_PERM((left), (right), (temp2)); \ + (kp) += (2 * 16); \ + for (i = 0; i < 8; i++) { \ + DES_SP_DECRYPT_ROUND((left), (right), (temp2), (kp)); \ + DES_SP_DECRYPT_ROUND((right), (left), (temp2), (kp)); \ + } \ + DES_FINAL_PERM((left), (right), (temp2)); \ + } while (0) + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) +extern void krb5int_des_do_encrypt_2(unsigned DES_INT32 *l, + unsigned DES_INT32 *r, + const unsigned DES_INT32 *k); +extern void krb5int_des_do_decrypt_2(unsigned DES_INT32 *l, + unsigned DES_INT32 *r, + const unsigned DES_INT32 *k); +#define DES_DO_ENCRYPT(L,R,K) krb5int_des_do_encrypt_2(&(L), &(R), (K)) +#define DES_DO_DECRYPT(L,R,K) krb5int_des_do_decrypt_2(&(L), &(R), (K)) +#else +#define DES_DO_ENCRYPT DES_DO_ENCRYPT_1 +#define DES_DO_DECRYPT DES_DO_DECRYPT_1 +#endif + +/* + * These are handy dandy utility thingies for straightening out bytes. + * Included here because they're used a couple of places. + */ +#define GET_HALF_BLOCK(lr, ip) ((lr) = load_32_be(ip), (ip) += 4) +#define PUT_HALF_BLOCK(lr, op) (store_32_be(lr, op), (op) += 4) + +/* Shorthand that we'll need in several places, for creating values that + really can hold 32 bits regardless of the prevailing int size. */ +#define FF_UINT32 ((unsigned DES_INT32) 0xFF) + +#endif /* __DES_TABLES_H__ */ diff --git a/src/lib/crypto/builtin/des/key_sched.c b/src/lib/crypto/builtin/des/key_sched.c new file mode 100644 index 000000000000..87f02b6a9856 --- /dev/null +++ b/src/lib/crypto/builtin/des/key_sched.c @@ -0,0 +1,62 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/key_sched.c */ +/* + * Copyright 1985, 1986, 1987, 1988, 1990 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. + */ + +/* + * This routine computes the DES key schedule given a key. The + * permutations and shifts have been done at compile time, resulting + * in a direct one-step mapping from the input key to the key + * schedule. + * + * Also checks parity and weak keys. + * + * Watch out for the subscripts -- most effectively start at 1 instead + * of at zero. Maybe some bugs in that area. + * + * In case the user wants to cache the computed key schedule, it is + * passed as an arg. Also implies that caller has explicit control + * over zeroing both the key schedule and the key. + * + * Originally written 6/85 by Steve Miller, MIT Project Athena. + */ + +#include "k5-int.h" +#include "des_int.h" + +int +mit_des_key_sched(mit_des_cblock k, mit_des_key_schedule schedule) +{ + mit_des_make_key_sched(k,schedule); + + if (!mit_des_check_key_parity(k)) /* bad parity --> return -1 */ + return(-1); + + if (mit_des_is_weak_key(k)) + return(-2); + + /* if key was good, return 0 */ + return 0; +} diff --git a/src/lib/crypto/builtin/des/keytest.data b/src/lib/crypto/builtin/des/keytest.data new file mode 100644 index 000000000000..7ff34eedcf9d --- /dev/null +++ b/src/lib/crypto/builtin/des/keytest.data @@ -0,0 +1,171 @@ +0101010101010101 95F8A5E5DD31D900 8000000000000000 +0101010101010101 DD7F121CA5015619 4000000000000000 +0101010101010101 2E8653104F3834EA 2000000000000000 +0101010101010101 4BD388FF6CD81D4F 1000000000000000 +0101010101010101 20B9E767B2FB1456 0800000000000000 +0101010101010101 55579380D77138EF 0400000000000000 +0101010101010101 6CC5DEFAAF04512F 0200000000000000 +0101010101010101 0D9F279BA5D87260 0100000000000000 +0101010101010101 D9031B0271BD5A0A 0080000000000000 +0101010101010101 424250B37C3DD951 0040000000000000 +0101010101010101 B8061B7ECD9A21E5 0020000000000000 +0101010101010101 F15D0F286B65BD28 0010000000000000 +0101010101010101 ADD0CC8D6E5DEBA1 0008000000000000 +0101010101010101 E6D5F82752AD63D1 0004000000000000 +0101010101010101 ECBFE3BD3F591A5E 0002000000000000 +0101010101010101 F356834379D165CD 0001000000000000 +0101010101010101 2B9F982F20037FA9 0000800000000000 +0101010101010101 889DE068A16F0BE6 0000400000000000 +0101010101010101 E19E275D846A1298 0000200000000000 +0101010101010101 329A8ED523D71AEC 0000100000000000 +0101010101010101 E7FCE22557D23C97 0000080000000000 +0101010101010101 12A9F5817FF2D65D 0000040000000000 +0101010101010101 A484C3AD38DC9C19 0000020000000000 +0101010101010101 FBE00A8A1EF8AD72 0000010000000000 +0101010101010101 750D079407521363 0000008000000000 +0101010101010101 64FEED9C724C2FAF 0000004000000000 +0101010101010101 F02B263B328E2B60 0000002000000000 +0101010101010101 9D64555A9A10B852 0000001000000000 +0101010101010101 D106FF0BED5255D7 0000000800000000 +0101010101010101 E1652C6B138C64A5 0000000400000000 +0101010101010101 E428581186EC8F46 0000000200000000 +0101010101010101 AEB5F5EDE22D1A36 0000000100000000 +0101010101010101 E943D7568AEC0C5C 0000000080000000 +0101010101010101 DF98C8276F54B04B 0000000040000000 +0101010101010101 B160E4680F6C696F 0000000020000000 +0101010101010101 FA0752B07D9C4AB8 0000000010000000 +0101010101010101 CA3A2B036DBC8502 0000000008000000 +0101010101010101 5E0905517BB59BCF 0000000004000000 +0101010101010101 814EEB3B91D90726 0000000002000000 +0101010101010101 4D49DB1532919C9F 0000000001000000 +0101010101010101 25EB5FC3F8CF0621 0000000000800000 +0101010101010101 AB6A20C0620D1C6F 0000000000400000 +0101010101010101 79E90DBC98F92CCA 0000000000200000 +0101010101010101 866ECEDD8072BB0E 0000000000100000 +0101010101010101 8B54536F2F3E64A8 0000000000080000 +0101010101010101 EA51D3975595B86B 0000000000040000 +0101010101010101 CAFFC6AC4542DE31 0000000000020000 +0101010101010101 8DD45A2DDF90796C 0000000000010000 +0101010101010101 1029D55E880EC2D0 0000000000008000 +0101010101010101 5D86CB23639DBEA9 0000000000004000 +0101010101010101 1D1CA853AE7C0C5F 0000000000002000 +0101010101010101 CE332329248F3228 0000000000001000 +0101010101010101 8405D1ABE24FB942 0000000000000800 +0101010101010101 E643D78090CA4207 0000000000000400 +0101010101010101 48221B9937748A23 0000000000000200 +0101010101010101 DD7C0BBD61FAFD54 0000000000000100 +0101010101010101 2FBC291A570DB5C4 0000000000000080 +0101010101010101 E07C30D7E4E26E12 0000000000000040 +0101010101010101 0953E2258E8E90A1 0000000000000020 +0101010101010101 5B711BC4CEEBF2EE 0000000000000010 +0101010101010101 CC083F1E6D9E85F6 0000000000000008 +0101010101010101 D2FD8867D50D2DFE 0000000000000004 +0101010101010101 06E7EA22CE92708F 0000000000000002 +0101010101010101 166B40B44ABA4BD6 0000000000000001 +8001010101010101 0000000000000000 95A8D72813DAA94D +4001010101010101 0000000000000000 0EEC1487DD8C26D5 +2001010101010101 0000000000000000 7AD16FFB79C45926 +1001010101010101 0000000000000000 D3746294CA6A6CF3 +0801010101010101 0000000000000000 809F5F873C1FD761 +0401010101010101 0000000000000000 C02FAFFEC989D1FC +0201010101010101 0000000000000000 4615AA1D33E72F10 +0180010101010101 0000000000000000 2055123350C00858 +0140010101010101 0000000000000000 DF3B99D6577397C8 +0120010101010101 0000000000000000 31FE17369B5288C9 +0110010101010101 0000000000000000 DFDD3CC64DAE1642 +0108010101010101 0000000000000000 178C83CE2B399D94 +0104010101010101 0000000000000000 50F636324A9B7F80 +0102010101010101 0000000000000000 A8468EE3BC18F06D +0101800101010101 0000000000000000 A2DC9E92FD3CDE92 +0101400101010101 0000000000000000 CAC09F797D031287 +0101200101010101 0000000000000000 90BA680B22AEB525 +0101100101010101 0000000000000000 CE7A24F350E280B6 +0101080101010101 0000000000000000 882BFF0AA01A0B87 +0101040101010101 0000000000000000 25610288924511C2 +0101020101010101 0000000000000000 C71516C29C75D170 +0101018001010101 0000000000000000 5199C29A52C9F059 +0101014001010101 0000000000000000 C22F0A294A71F29F +0101012001010101 0000000000000000 EE371483714C02EA +0101011001010101 0000000000000000 A81FBD448F9E522F +0101010801010101 0000000000000000 4F644C92E192DFED +0101010401010101 0000000000000000 1AFA9A66A6DF92AE +0101010201010101 0000000000000000 B3C1CC715CB879D8 +0101010180010101 0000000000000000 19D032E64AB0BD8B +0101010140010101 0000000000000000 3CFAA7A7DC8720DC +0101010120010101 0000000000000000 B7265F7F447AC6F3 +0101010110010101 0000000000000000 9DB73B3C0D163F54 +0101010108010101 0000000000000000 8181B65BABF4A975 +0101010104010101 0000000000000000 93C9B64042EAA240 +0101010102010101 0000000000000000 5570530829705592 +0101010101800101 0000000000000000 8638809E878787A0 +0101010101400101 0000000000000000 41B9A79AF79AC208 +0101010101200101 0000000000000000 7A9BE42F2009A892 +0101010101100101 0000000000000000 29038D56BA6D2745 +0101010101080101 0000000000000000 5495C6ABF1E5DF51 +0101010101040101 0000000000000000 AE13DBD561488933 +0101010101020101 0000000000000000 024D1FFA8904E389 +0101010101018001 0000000000000000 D1399712F99BF02E +0101010101014001 0000000000000000 14C1D7C1CFFEC79E +0101010101012001 0000000000000000 1DE5279DAE3BED6F +0101010101011001 0000000000000000 E941A33F85501303 +0101010101010801 0000000000000000 DA99DBBC9A03F379 +0101010101010401 0000000000000000 B7FC92F91D8E92E9 +0101010101010201 0000000000000000 AE8E5CAA3CA04E85 +0101010101010180 0000000000000000 9CC62DF43B6EED74 +0101010101010140 0000000000000000 D863DBB5C59A91A0 +0101010101010120 0000000000000000 A1AB2190545B91D7 +0101010101010110 0000000000000000 0875041E64C570F7 +0101010101010108 0000000000000000 5A594528BEBEF1CC +0101010101010104 0000000000000000 FCDB3291DE21F0C0 +0101010101010102 0000000000000000 869EFD7F9F265A09 +1046913489980131 0000000000000000 88D55E54F54C97B4 +1007103489988020 0000000000000000 0C0CC00C83EA48FD +10071034C8980120 0000000000000000 83BC8EF3A6570183 +1046103489988020 0000000000000000 DF725DCAD94EA2E9 +1086911519190101 0000000000000000 E652B53B550BE8B0 +1086911519580101 0000000000000000 AF527120C485CBB0 +5107B01519580101 0000000000000000 0F04CE393DB926D5 +1007B01519190101 0000000000000000 C9F00FFC74079067 +3107915498080101 0000000000000000 7CFD82A593252B4E +3107919498080101 0000000000000000 CB49A2F9E91363E3 +10079115B9080140 0000000000000000 00B588BE70D23F56 +3107911598080140 0000000000000000 406A9A6AB43399AE +1007D01589980101 0000000000000000 6CB773611DCA9ADA +9107911589980101 0000000000000000 67FD21C17DBB5D70 +9107D01589190101 0000000000000000 9592CB4110430787 +1007D01598980120 0000000000000000 A6B7FF68A318DDD3 +1007940498190101 0000000000000000 4D102196C914CA16 +0107910491190401 0000000000000000 2DFA9F4573594965 +0107910491190101 0000000000000000 B46604816C0E0774 +0107940491190401 0000000000000000 6E7E6221A4F34E87 +19079210981A0101 0000000000000000 AA85E74643233199 +1007911998190801 0000000000000000 2E5A19DB4D1962D6 +10079119981A0801 0000000000000000 23A866A809D30894 +1007921098190101 0000000000000000 D812D961F017D320 +100791159819010B 0000000000000000 055605816E58608F +1004801598190101 0000000000000000 ABD88E8B1B7716F1 +1004801598190102 0000000000000000 537AC95BE69DA1E1 +1004801598190108 0000000000000000 AED0F6AE3C25CDD8 +1002911598100104 0000000000000000 B3E35A5EE53E7B8D +1002911598190104 0000000000000000 61C79C71921A2EF8 +1002911598100201 0000000000000000 E2F5728F0995013C +1002911698100101 0000000000000000 1AEAC39A61F0A464 +7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B +0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271 +07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A +3849674C2602319E 51454B582DDF440A 7178876E01F19B2A +04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095 +0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B +0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09 +43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A +07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F +04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088 +37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77 +1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A +584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56 +025816164629B007 480D39006EE762F2 A1F9915541020B56 +49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556 +4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC +49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A +018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41 +1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793 diff --git a/src/lib/crypto/builtin/des/t_verify.c b/src/lib/crypto/builtin/des/t_verify.c new file mode 100644 index 000000000000..1f3239fed681 --- /dev/null +++ b/src/lib/crypto/builtin/des/t_verify.c @@ -0,0 +1,419 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/t_verify.c */ +/* + * Copyright 1988, 1990 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. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * + * Program to test the correctness of the DES library + * implementation. + * + * exit returns 0 ==> success + * -1 ==> error + */ + +#include "k5-int.h" +#include "des_int.h" +#include <stdio.h> +#include "com_err.h" + +static void do_encrypt(unsigned char *, unsigned char *); +static void do_decrypt(unsigned char *, unsigned char *); + +char *progname; +int nflag = 2; +int vflag; +int mflag; +int zflag; +int pid; +int mit_des_debug; + +unsigned char cipher_text[64]; +unsigned char clear_text[64] = "Now is the time for all " ; +unsigned char clear_text2[64] = "7654321 Now is the time for "; +unsigned char clear_text3[64] = {2,0,0,0, 1,0,0,0}; +unsigned char output[64]; +unsigned char zero_text[8] = {0x0,0,0,0,0,0,0,0}; +unsigned char msb_text[8] = {0x0,0,0,0, 0,0,0,0x40}; /* to ANSI MSB */ +unsigned char *input; + +/* 0x0123456789abcdef */ +unsigned char default_key[8] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef +}; +unsigned char key2[8] = { 0x08,0x19,0x2a,0x3b,0x4c,0x5d,0x6e,0x7f }; +unsigned char key3[8] = { 0x80,1,1,1,1,1,1,1 }; +mit_des_cblock s_key; +unsigned char default_ivec[8] = { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef +}; +unsigned char *ivec; +unsigned char zero_key[8] = {1,1,1,1,1,1,1,1}; /* just parity bits */ + +unsigned char cipher1[8] = { + 0x25,0xdd,0xac,0x3e,0x96,0x17,0x64,0x67 +}; +unsigned char cipher2[8] = { + 0x3f,0xa4,0x0e,0x8a,0x98,0x4d,0x48,0x15 +}; +unsigned char cipher3[64] = { + 0xe5,0xc7,0xcd,0xde,0x87,0x2b,0xf2,0x7c, + 0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f, + 0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6 +}; +unsigned char checksum[8] = { + 0x58,0xd2,0xe7,0x7e,0x86,0x06,0x27,0x33 +}; + +unsigned char zresult[8] = { + 0x8c, 0xa6, 0x4d, 0xe9, 0xc1, 0xb1, 0x23, 0xa7 +}; + +unsigned char mresult[8] = { + 0xa3, 0x80, 0xe0, 0x2a, 0x6b, 0xe5, 0x46, 0x96 +}; + + +/* + * Can also add : + * plaintext = 0, key = 0, cipher = 0x8ca64de9c1b123a7 (or is it a 1?) + */ + +mit_des_key_schedule sched; + +int +main(argc,argv) + int argc; + char *argv[]; +{ + /* Local Declarations */ + size_t in_length; + int retval; + int i, j; + +#ifdef WINDOWS + /* Set screen window buffer to infinite size -- MS default is tiny. */ + _wsetscreenbuf (fileno (stdout), _WINBUFINF); +#endif + progname=argv[0]; /* salt away invoking program */ + + while (--argc > 0 && (*++argv)[0] == '-') + for (i=1; argv[0][i] != '\0'; i++) { + switch (argv[0][i]) { + + /* debug flag */ + case 'd': + mit_des_debug=3; + continue; + + case 'z': + zflag = 1; + continue; + + case 'm': + mflag = 1; + continue; + + default: + printf("%s: illegal flag \"%c\" ", + progname,argv[0][i]); + exit(1); + } + }; + + if (argc) { + fprintf(stderr, "Usage: %s [-dmz]\n", progname); + exit(1); + } + + /* do some initialisation */ + + /* use known input and key */ + + /* ECB zero text zero key */ + if (zflag) { + input = zero_text; + mit_des_key_sched(zero_key, sched); + printf("plaintext = key = 0, cipher = 0x8ca64de9c1b123a7\n"); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n"); + do_decrypt(output,cipher_text); + if ( memcmp((char *)cipher_text, (char *)zresult, 8) ) { + printf("verify: error in zero key test\n"); + exit(-1); + } + + exit(0); + } + + if (mflag) { + input = msb_text; + mit_des_key_sched(key3, sched); + printf("plaintext = 0x00 00 00 00 00 00 00 40, "); + printf("key = 0x80 01 01 01 01 01 01 01\n"); + printf(" cipher = 0xa380e02a6be54696\n"); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) { + printf("%02x ",cipher_text[j]); + } + printf("\n"); + do_decrypt(output,cipher_text); + if ( memcmp((char *)cipher_text, (char *)mresult, 8) ) { + printf("verify: error in msb test\n"); + exit(-1); + } + exit(0); + } + + /* ECB mode Davies and Price */ + { + input = zero_text; + mit_des_key_sched(key2, sched); + printf("Examples per FIPS publication 81, keys ivs and cipher\n"); + printf("in hex. These are the correct answers, see below for\n"); + printf("the actual answers.\n\n"); + printf("Examples per Davies and Price.\n\n"); + printf("EXAMPLE ECB\tkey = 08192a3b4c5d6e7f\n"); + printf("\tclear = 0\n"); + printf("\tcipher = 25 dd ac 3e 96 17 64 67\n"); + printf("ACTUAL ECB\n"); + printf("\tclear \"%s\"\n", input); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n\n"); + do_decrypt(output,cipher_text); + if ( memcmp((char *)cipher_text, (char *)cipher1, 8) ) { + printf("verify: error in ECB encryption\n"); + exit(-1); + } + else + printf("verify: ECB encryption is correct\n\n"); + } + + /* ECB mode */ + { + mit_des_key_sched(default_key, sched); + input = clear_text; + ivec = default_ivec; + printf("EXAMPLE ECB\tkey = 0123456789abcdef\n"); + printf("\tclear = \"Now is the time for all \"\n"); + printf("\tcipher = 3f a4 0e 8a 98 4d 48 15 ...\n"); + printf("ACTUAL ECB\n\tclear \"%s\"",input); + do_encrypt(input,cipher_text); + printf("\n\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) { + printf("%02x ",cipher_text[j]); + } + printf("\n\n"); + do_decrypt(output,cipher_text); + if ( memcmp((char *)cipher_text, (char *)cipher2, 8) ) { + printf("verify: error in ECB encryption\n"); + exit(-1); + } + else + printf("verify: ECB encryption is correct\n\n"); + } + + /* CBC mode */ + printf("EXAMPLE CBC\tkey = 0123456789abcdef"); + printf("\tiv = 1234567890abcdef\n"); + printf("\tclear = \"Now is the time for all \"\n"); + printf("\tcipher =\te5 c7 cd de 87 2b f2 7c\n"); + printf("\t\t\t43 e9 34 00 8c 38 9c 0f\n"); + printf("\t\t\t68 37 88 49 9a 7c 05 f6\n"); + + printf("ACTUAL CBC\n\tclear \"%s\"\n",input); + in_length = strlen((char *)input); + if ((retval = mit_des_cbc_encrypt((const mit_des_cblock *) input, + (mit_des_cblock *) cipher_text, + (size_t) in_length, + sched, + ivec, + MIT_DES_ENCRYPT))) { + com_err("des verify", retval, "can't encrypt"); + exit(-1); + } + printf("\tciphertext = (low to high bytes)\n"); + for (i = 0; i <= 2; i++) { + printf("\t\t"); + for (j = 0; j <= 7; j++) { + printf("%02x ",cipher_text[i*8+j]); + } + printf("\n"); + } + if ((retval = mit_des_cbc_encrypt((const mit_des_cblock *) cipher_text, + (mit_des_cblock *) clear_text, + (size_t) in_length, + sched, + ivec, + MIT_DES_DECRYPT))) { + com_err("des verify", retval, "can't decrypt"); + exit(-1); + } + printf("\tdecrypted clear_text = \"%s\"\n",clear_text); + + if ( memcmp((char *)cipher_text, (char *)cipher3, in_length) ) { + printf("verify: error in CBC encryption\n"); + exit(-1); + } + else + printf("verify: CBC encryption is correct\n\n"); + + printf("EXAMPLE CBC checksum"); + printf("\tkey = 0123456789abcdef\tiv = 1234567890abcdef\n"); + printf("\tclear =\t\t\"7654321 Now is the time for \"\n"); + printf("\tchecksum\t58 d2 e7 7e 86 06 27 33, "); + printf("or some part thereof\n"); + input = clear_text2; + mit_des_cbc_cksum(input,cipher_text, strlen((char *)input), + sched,ivec); + printf("ACTUAL CBC checksum\n"); + printf("\t\tencrypted cksum = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n\n"); + if ( memcmp((char *)cipher_text, (char *)checksum, 8) ) { + printf("verify: error in CBC cheksum\n"); + exit(-1); + } + else + printf("verify: CBC checksum is correct\n\n"); + + exit(0); +} + +#if 0 +void +flip(array) + char *array; +{ + register int old,new,i,j; + /* flips the bit order within each byte from 0 lsb to 0 msb */ + for (i = 0; i<=7; i++) { + old = *array; + new = 0; + for (j = 0; j<=7; j++) { + if (old & 01) + new = new | 01; + if (j < 7) { + old = old >> 1; + new = new << 1; + } + } + *array = new; + array++; + } +} +#endif + +static void +do_encrypt(in,out) + unsigned char *in; + unsigned char *out; +{ + int i, j; + for (i =1; i<=nflag; i++) { + mit_des_cbc_encrypt((const mit_des_cblock *)in, + (mit_des_cblock *)out, + 8, + sched, + zero_text, + MIT_DES_ENCRYPT); + if (mit_des_debug) { + printf("\nclear %s\n",in); + for (j = 0; j<=7; j++) + printf("%02X ",in[j] & 0xff); + printf("\tcipher "); + for (j = 0; j<=7; j++) + printf("%02X ",out[j] & 0xff); + } + } +} + +static void +do_decrypt(in,out) + unsigned char *out; + unsigned char *in; + /* try to invert it */ +{ + int i, j; + for (i =1; i<=nflag; i++) { + mit_des_cbc_encrypt((const mit_des_cblock *)out, + (mit_des_cblock *)in, + 8, + sched, + zero_text, + MIT_DES_DECRYPT); + if (mit_des_debug) { + printf("clear %s\n",in); + for (j = 0; j<=7; j++) + printf("%02X ",in[j] & 0xff); + printf("\tcipher "); + for (j = 0; j<=7; j++) + printf("%02X ",out[j] & 0xff); + } + } +} + +/* + * Fake out the DES library, for the purposes of testing. + */ + +int +mit_des_is_weak_key(key) + mit_des_cblock key; +{ + return 0; /* fake it out for testing */ +} diff --git a/src/lib/crypto/builtin/des/weak_key.c b/src/lib/crypto/builtin/des/weak_key.c new file mode 100644 index 000000000000..eb41b267dfd5 --- /dev/null +++ b/src/lib/crypto/builtin/des/weak_key.c @@ -0,0 +1,86 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/weak_key.c */ +/* + * Copyright 1989,1990 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. + */ + +/* + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * These routines form the library interface to the DES facilities. + * + * Originally written 8/85 by Steve Miller, MIT Project Athena. + */ + +#include "k5-int.h" +#include "des_int.h" + +/* + * The following are the weak DES keys: + */ +static const mit_des_cblock weak[16] = { + /* weak keys */ + {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, + {0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe}, + {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e}, + {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1}, + + /* semi-weak */ + {0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe}, + {0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01}, + + {0x1f,0xe0,0x1f,0xe0,0x0e,0xf1,0x0e,0xf1}, + {0xe0,0x1f,0xe0,0x1f,0xf1,0x0e,0xf1,0x0e}, + + {0x01,0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1}, + {0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1,0x01}, + + {0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e,0xfe}, + {0xfe,0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e}, + + {0x01,0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e}, + {0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e,0x01}, + + {0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1,0xfe}, + {0xfe,0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1} +}; + +/* + * mit_des_is_weak_key: returns true iff key is a [semi-]weak des key. + * + * Requires: key has correct odd parity. + */ +int +mit_des_is_weak_key(mit_des_cblock key) +{ + unsigned int i; + const mit_des_cblock *weak_p = weak; + + for (i = 0; i < (sizeof(weak)/sizeof(mit_des_cblock)); i++) { + if (!memcmp(weak_p++,key,sizeof(mit_des_cblock))) + return 1; + } + + return 0; +} diff --git a/src/lib/crypto/builtin/enc_provider/Makefile.in b/src/lib/crypto/builtin/enc_provider/Makefile.in new file mode 100644 index 000000000000..4fd3311b4fb1 --- /dev/null +++ b/src/lib/crypto/builtin/enc_provider/Makefile.in @@ -0,0 +1,45 @@ +mydir=lib$(S)crypto$(S)builtin$(S)enc_provider +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/../des \ + -I$(srcdir)/../aes \ + -I$(srcdir)/../camellia \ + -I$(srcdir)/../../krb \ + -I$(srcdir)/.. + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\enc_provider +##DOS##OBJFILE = ..\..\$(OUTPRE)enc_provider.lst + +STLIBOBJS= \ + des.o \ + des3.o \ + rc4.o \ + aes.o \ + camellia.o + +OBJS= \ + $(OUTPRE)des.$(OBJEXT) \ + $(OUTPRE)des3.$(OBJEXT) \ + $(OUTPRE)aes.$(OBJEXT) \ + $(OUTPRE)camellia.$(OBJEXT) \ + $(OUTPRE)rc4.$(OBJEXT) + +SRCS= \ + $(srcdir)/des.c \ + $(srcdir)/des3.c \ + $(srcdir)/aes.c \ + $(srcdir)/camellia.c \ + $(srcdir)/rc4.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/src/lib/crypto/builtin/enc_provider/aes.c b/src/lib/crypto/builtin/enc_provider/aes.c new file mode 100644 index 000000000000..2a5d8e39775d --- /dev/null +++ b/src/lib/crypto/builtin/enc_provider/aes.c @@ -0,0 +1,406 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/enc_provider/aes.c */ +/* + * Copyright (C) 2003, 2007, 2008 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. + */ + +#include "crypto_int.h" +#include "aes.h" + +/* + * Private per-key data to cache after first generation. We don't + * want to mess with the imported AES implementation too much, so + * we'll just use two copies of its context, one for encryption and + * one for decryption, and use the #rounds field as a flag for whether + * we've initialized each half. + */ +struct aes_key_info_cache { + aes_ctx enc_ctx, dec_ctx; + krb5_boolean aesni; +}; +#define CACHE(X) ((struct aes_key_info_cache *)((X)->cache)) + +#ifdef AESNI + +/* Use AES-NI instructions (via assembly functions) when possible. */ + +#include <cpuid.h> + +struct aes_data +{ + unsigned char *in_block; + unsigned char *out_block; + uint32_t *expanded_key; + unsigned char *iv; + size_t num_blocks; +}; + +void k5_iEncExpandKey128(unsigned char *key, uint32_t *expanded_key); +void k5_iEncExpandKey256(unsigned char *key, uint32_t *expanded_key); +void k5_iDecExpandKey256(unsigned char *key, uint32_t *expanded_key); +void k5_iDecExpandKey128(unsigned char *key, uint32_t *expanded_key); + +void k5_iEnc128_CBC(struct aes_data *data); +void k5_iDec128_CBC(struct aes_data *data); +void k5_iEnc256_CBC(struct aes_data *data); +void k5_iDec256_CBC(struct aes_data *data); + +static krb5_boolean +aesni_supported_by_cpu() +{ + unsigned int a, b, c, d; + + return __get_cpuid(1, &a, &b, &c, &d) && (c & (1 << 25)); +} + +static inline krb5_boolean +aesni_supported(krb5_key key) +{ + return CACHE(key)->aesni; +} + +static void +aesni_expand_enc_key(krb5_key key) +{ + struct aes_key_info_cache *cache = CACHE(key); + + if (key->keyblock.length == 16) + k5_iEncExpandKey128(key->keyblock.contents, cache->enc_ctx.k_sch); + else + k5_iEncExpandKey256(key->keyblock.contents, cache->enc_ctx.k_sch); + cache->enc_ctx.n_rnd = 1; +} + +static void +aesni_expand_dec_key(krb5_key key) +{ + struct aes_key_info_cache *cache = CACHE(key); + + if (key->keyblock.length == 16) + k5_iDecExpandKey128(key->keyblock.contents, cache->dec_ctx.k_sch); + else + k5_iDecExpandKey256(key->keyblock.contents, cache->dec_ctx.k_sch); + cache->dec_ctx.n_rnd = 1; +} + +static inline void +aesni_enc(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + struct aes_key_info_cache *cache = CACHE(key); + struct aes_data d; + + d.in_block = data; + d.out_block = data; + d.expanded_key = cache->enc_ctx.k_sch; + d.iv = iv; + d.num_blocks = nblocks; + if (key->keyblock.length == 16) + k5_iEnc128_CBC(&d); + else + k5_iEnc256_CBC(&d); +} + +static inline void +aesni_dec(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + struct aes_key_info_cache *cache = CACHE(key); + struct aes_data d; + + d.in_block = data; + d.out_block = data; + d.expanded_key = cache->dec_ctx.k_sch; + d.iv = iv; + d.num_blocks = nblocks; + if (key->keyblock.length == 16) + k5_iDec128_CBC(&d); + else + k5_iDec256_CBC(&d); +} + +#else /* not AESNI */ + +#define aesni_supported_by_cpu() FALSE +#define aesni_supported(key) FALSE +#define aesni_expand_enc_key(key) +#define aesni_expand_dec_key(key) +#define aesni_enc(key, data, nblocks, iv) +#define aesni_dec(key, data, nblocks, iv) + +#endif + +/* out = out ^ in */ +static inline void +xorblock(const unsigned char *in, unsigned char *out) +{ + size_t q; + + for (q = 0; q < BLOCK_SIZE; q += 4) + store_32_n(load_32_n(out + q) ^ load_32_n(in + q), out + q); +} + +static inline krb5_error_code +init_key_cache(krb5_key key) +{ + if (key->cache != NULL) + return 0; + key->cache = malloc(sizeof(struct aes_key_info_cache)); + if (key->cache == NULL) + return ENOMEM; + CACHE(key)->enc_ctx.n_rnd = CACHE(key)->dec_ctx.n_rnd = 0; + CACHE(key)->aesni = aesni_supported_by_cpu(); + return 0; +} + +static inline void +expand_enc_key(krb5_key key) +{ + if (CACHE(key)->enc_ctx.n_rnd) + return; + if (aesni_supported(key)) + aesni_expand_enc_key(key); + else if (aes_enc_key(key->keyblock.contents, key->keyblock.length, + &CACHE(key)->enc_ctx) != aes_good) + abort(); +} + +static inline void +expand_dec_key(krb5_key key) +{ + if (CACHE(key)->dec_ctx.n_rnd) + return; + if (aesni_supported(key)) + aesni_expand_dec_key(key); + else if (aes_dec_key(key->keyblock.contents, key->keyblock.length, + &CACHE(key)->dec_ctx) != aes_good) + abort(); +} + +/* CBC encrypt nblocks blocks of data in place, using and updating iv. */ +static inline void +cbc_enc(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + if (aesni_supported(key)) { + aesni_enc(key, data, nblocks, iv); + return; + } + for (; nblocks > 0; nblocks--, data += BLOCK_SIZE) { + xorblock(iv, data); + if (aes_enc_blk(data, data, &CACHE(key)->enc_ctx) != aes_good) + abort(); + memcpy(iv, data, BLOCK_SIZE); + } +} + +/* CBC decrypt nblocks blocks of data in place, using and updating iv. */ +static inline void +cbc_dec(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + unsigned char last_cipherblock[BLOCK_SIZE]; + + if (aesni_supported(key)) { + aesni_dec(key, data, nblocks, iv); + return; + } + assert(nblocks > 0); + data += (nblocks - 1) * BLOCK_SIZE; + memcpy(last_cipherblock, data, BLOCK_SIZE); + for (; nblocks > 0; nblocks--, data -= BLOCK_SIZE) { + if (aes_dec_blk(data, data, &CACHE(key)->dec_ctx) != aes_good) + abort(); + xorblock(nblocks == 1 ? iv : data - BLOCK_SIZE, data); + } + memcpy(iv, last_cipherblock, BLOCK_SIZE); +} + +krb5_error_code +krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + unsigned char iv[BLOCK_SIZE], block[BLOCK_SIZE]; + unsigned char blockN2[BLOCK_SIZE], blockN1[BLOCK_SIZE]; + size_t input_length, nblocks, ncontig; + struct iov_cursor cursor; + + if (init_key_cache(key)) + return ENOMEM; + expand_enc_key(key); + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (nblocks == 1) { + k5_iov_cursor_get(&cursor, block); + memset(iv, 0, BLOCK_SIZE); + cbc_enc(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + return 0; + } + + if (ivec != NULL) + memcpy(iv, ivec->data, BLOCK_SIZE); + else + memset(iv, 0, BLOCK_SIZE); + + while (nblocks > 2) { + ncontig = iov_cursor_contig_blocks(&cursor); + if (ncontig > 0) { + /* Encrypt a series of contiguous blocks in place if we can, but + * don't touch the last two blocks. */ + ncontig = (ncontig > nblocks - 2) ? nblocks - 2 : ncontig; + cbc_enc(key, iov_cursor_ptr(&cursor), ncontig, iv); + iov_cursor_advance(&cursor, ncontig); + nblocks -= ncontig; + } else { + k5_iov_cursor_get(&cursor, block); + cbc_enc(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + nblocks--; + } + } + + /* Encrypt the last two blocks and put them back in reverse order, possibly + * truncating the encrypted second-to-last block. */ + k5_iov_cursor_get(&cursor, blockN2); + k5_iov_cursor_get(&cursor, blockN1); + cbc_enc(key, blockN2, 1, iv); + cbc_enc(key, blockN1, 1, iv); + k5_iov_cursor_put(&cursor, blockN1); + k5_iov_cursor_put(&cursor, blockN2); + + if (ivec != NULL) + memcpy(ivec->data, iv, BLOCK_SIZE); + + return 0; +} + +krb5_error_code +krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + unsigned char iv[BLOCK_SIZE], dummy_iv[BLOCK_SIZE], block[BLOCK_SIZE]; + unsigned char blockN2[BLOCK_SIZE], blockN1[BLOCK_SIZE]; + size_t input_length, last_len, nblocks, ncontig; + struct iov_cursor cursor; + + if (init_key_cache(key)) + return ENOMEM; + expand_dec_key(key); + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + last_len = input_length - (nblocks - 1) * BLOCK_SIZE; + if (nblocks == 1) { + k5_iov_cursor_get(&cursor, block); + memset(iv, 0, BLOCK_SIZE); + cbc_dec(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + return 0; + } + + if (ivec != NULL) + memcpy(iv, ivec->data, BLOCK_SIZE); + else + memset(iv, 0, BLOCK_SIZE); + + while (nblocks > 2) { + ncontig = iov_cursor_contig_blocks(&cursor); + if (ncontig > 0) { + /* Decrypt a series of contiguous blocks in place if we can, but + * don't touch the last two blocks. */ + ncontig = (ncontig > nblocks - 2) ? nblocks - 2 : ncontig; + cbc_dec(key, iov_cursor_ptr(&cursor), ncontig, iv); + iov_cursor_advance(&cursor, ncontig); + nblocks -= ncontig; + } else { + k5_iov_cursor_get(&cursor, block); + cbc_dec(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + nblocks--; + } + } + + /* Get the last two ciphertext blocks. Save the first as the new iv. */ + k5_iov_cursor_get(&cursor, blockN2); + k5_iov_cursor_get(&cursor, blockN1); + if (ivec != NULL) + memcpy(ivec->data, blockN2, BLOCK_SIZE); + + /* Decrypt the second-to-last ciphertext block, using the final ciphertext + * block as the CBC IV. This produces the final plaintext block. */ + memcpy(dummy_iv, blockN1, sizeof(dummy_iv)); + cbc_dec(key, blockN2, 1, dummy_iv); + + /* Use the final bits of the decrypted plaintext to pad the last ciphertext + * block, and decrypt it to produce the second-to-last plaintext block. */ + memcpy(blockN1 + last_len, blockN2 + last_len, BLOCK_SIZE - last_len); + cbc_dec(key, blockN1, 1, iv); + + /* Put the last two plaintext blocks back into the iovec. */ + k5_iov_cursor_put(&cursor, blockN1); + k5_iov_cursor_put(&cursor, blockN2); + + return 0; +} + +static krb5_error_code +aes_init_state(const krb5_keyblock *key, krb5_keyusage usage, + krb5_data *state) +{ + state->length = 16; + state->data = malloc(16); + if (state->data == NULL) + return ENOMEM; + memset(state->data, 0, state->length); + return 0; +} + +static void +aes_key_cleanup(krb5_key key) +{ + zapfree(key->cache, sizeof(struct aes_key_info_cache)); +} + +const struct krb5_enc_provider krb5int_enc_aes128 = { + 16, + 16, 16, + krb5int_aes_encrypt, + krb5int_aes_decrypt, + NULL, + aes_init_state, + krb5int_default_free_state, + aes_key_cleanup +}; + +const struct krb5_enc_provider krb5int_enc_aes256 = { + 16, + 32, 32, + krb5int_aes_encrypt, + krb5int_aes_decrypt, + NULL, + aes_init_state, + krb5int_default_free_state, + aes_key_cleanup +}; diff --git a/src/lib/crypto/builtin/enc_provider/camellia.c b/src/lib/crypto/builtin/enc_provider/camellia.c new file mode 100644 index 000000000000..db1258086798 --- /dev/null +++ b/src/lib/crypto/builtin/enc_provider/camellia.c @@ -0,0 +1,315 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/enc_provider/camellia.c - Camellia enc provider */ +/* + * Copyright (C) 2009, 2010 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. + */ + +#include "crypto_int.h" +#include "camellia.h" + +/* + * Private per-key data to cache after first generation. We don't want to mess + * with the imported Camellia implementation too much, so we'll just use two + * copies of its context, one for encryption and one for decryption, and use + * the keybitlen field as a flag for whether we've initialized each half. + */ +struct camellia_key_info_cache { + camellia_ctx enc_ctx, dec_ctx; +}; +#define CACHE(X) ((struct camellia_key_info_cache *)((X)->cache)) + +/* out = out ^ in */ +static inline void +xorblock(const unsigned char *in, unsigned char *out) +{ + size_t q; + + for (q = 0; q < BLOCK_SIZE; q += 4) + store_32_n(load_32_n(out + q) ^ load_32_n(in + q), out + q); +} + +static inline krb5_error_code +init_key_cache(krb5_key key) +{ + if (key->cache != NULL) + return 0; + key->cache = malloc(sizeof(struct camellia_key_info_cache)); + if (key->cache == NULL) + return ENOMEM; + CACHE(key)->enc_ctx.keybitlen = CACHE(key)->dec_ctx.keybitlen = 0; + return 0; +} + +static inline void +expand_enc_key(krb5_key key) +{ + if (CACHE(key)->enc_ctx.keybitlen) + return; + if (camellia_enc_key(key->keyblock.contents, key->keyblock.length, + &CACHE(key)->enc_ctx) != camellia_good) + abort(); +} + +static inline void +expand_dec_key(krb5_key key) +{ + if (CACHE(key)->dec_ctx.keybitlen) + return; + if (camellia_dec_key(key->keyblock.contents, key->keyblock.length, + &CACHE(key)->dec_ctx) != camellia_good) + abort(); +} + +/* CBC encrypt nblocks blocks of data in place, using and updating iv. */ +static inline void +cbc_enc(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + for (; nblocks > 0; nblocks--, data += BLOCK_SIZE) { + xorblock(iv, data); + if (camellia_enc_blk(data, data, &CACHE(key)->enc_ctx) != + camellia_good) + abort(); + memcpy(iv, data, BLOCK_SIZE); + } +} + +/* CBC decrypt nblocks blocks of data in place, using and updating iv. */ +static inline void +cbc_dec(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + unsigned char last_cipherblock[BLOCK_SIZE]; + + assert(nblocks > 0); + data += (nblocks - 1) * BLOCK_SIZE; + memcpy(last_cipherblock, data, BLOCK_SIZE); + for (; nblocks > 0; nblocks--, data -= BLOCK_SIZE) { + if (camellia_dec_blk(data, data, &CACHE(key)->dec_ctx) != + camellia_good) + abort(); + xorblock(nblocks == 1 ? iv : data - BLOCK_SIZE, data); + } + memcpy(iv, last_cipherblock, BLOCK_SIZE); +} + +static krb5_error_code +krb5int_camellia_encrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + unsigned char iv[BLOCK_SIZE], block[BLOCK_SIZE]; + unsigned char blockN2[BLOCK_SIZE], blockN1[BLOCK_SIZE]; + size_t input_length, nblocks, ncontig; + struct iov_cursor cursor; + + if (init_key_cache(key)) + return ENOMEM; + expand_enc_key(key); + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (nblocks == 1) { + k5_iov_cursor_get(&cursor, block); + memset(iv, 0, BLOCK_SIZE); + cbc_enc(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + return 0; + } + + if (ivec != NULL) + memcpy(iv, ivec->data, BLOCK_SIZE); + else + memset(iv, 0, BLOCK_SIZE); + + while (nblocks > 2) { + ncontig = iov_cursor_contig_blocks(&cursor); + if (ncontig > 0) { + /* Encrypt a series of contiguous blocks in place if we can, but + * don't touch the last two blocks. */ + ncontig = (ncontig > nblocks - 2) ? nblocks - 2 : ncontig; + cbc_enc(key, iov_cursor_ptr(&cursor), ncontig, iv); + iov_cursor_advance(&cursor, ncontig); + nblocks -= ncontig; + } else { + k5_iov_cursor_get(&cursor, block); + cbc_enc(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + nblocks--; + } + } + + /* Encrypt the last two blocks and put them back in reverse order, possibly + * truncating the encrypted second-to-last block. */ + k5_iov_cursor_get(&cursor, blockN2); + k5_iov_cursor_get(&cursor, blockN1); + cbc_enc(key, blockN2, 1, iv); + cbc_enc(key, blockN1, 1, iv); + k5_iov_cursor_put(&cursor, blockN1); + k5_iov_cursor_put(&cursor, blockN2); + + if (ivec != NULL) + memcpy(ivec->data, iv, BLOCK_SIZE); + + return 0; +} + +static krb5_error_code +krb5int_camellia_decrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + unsigned char iv[BLOCK_SIZE], dummy_iv[BLOCK_SIZE], block[BLOCK_SIZE]; + unsigned char blockN2[BLOCK_SIZE], blockN1[BLOCK_SIZE]; + size_t input_length, last_len, nblocks, ncontig; + struct iov_cursor cursor; + + if (init_key_cache(key)) + return ENOMEM; + expand_dec_key(key); + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + last_len = input_length - (nblocks - 1) * BLOCK_SIZE; + if (nblocks == 1) { + k5_iov_cursor_get(&cursor, block); + memset(iv, 0, BLOCK_SIZE); + cbc_dec(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + return 0; + } + + if (ivec != NULL) + memcpy(iv, ivec->data, BLOCK_SIZE); + else + memset(iv, 0, BLOCK_SIZE); + + while (nblocks > 2) { + ncontig = iov_cursor_contig_blocks(&cursor); + if (ncontig > 0) { + /* Encrypt a series of contiguous blocks in place if we can, but + * don't touch the last two blocks. */ + ncontig = (ncontig > nblocks - 2) ? nblocks - 2 : ncontig; + cbc_dec(key, iov_cursor_ptr(&cursor), ncontig, iv); + iov_cursor_advance(&cursor, ncontig); + nblocks -= ncontig; + } else { + k5_iov_cursor_get(&cursor, block); + cbc_dec(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + nblocks--; + } + } + + /* Get the last two ciphertext blocks. Save the first as the new iv. */ + k5_iov_cursor_get(&cursor, blockN2); + k5_iov_cursor_get(&cursor, blockN1); + if (ivec != NULL) + memcpy(ivec->data, blockN2, BLOCK_SIZE); + + /* Decrypt the second-to-last ciphertext block, using the final ciphertext + * block as the CBC IV. This produces the final plaintext block. */ + memcpy(dummy_iv, blockN1, sizeof(dummy_iv)); + cbc_dec(key, blockN2, 1, dummy_iv); + + /* Use the final bits of the decrypted plaintext to pad the last ciphertext + * block, and decrypt it to produce the second-to-last plaintext block. */ + memcpy(blockN1 + last_len, blockN2 + last_len, BLOCK_SIZE - last_len); + cbc_dec(key, blockN1, 1, iv); + + /* Put the last two plaintext blocks back into the iovec. */ + k5_iov_cursor_put(&cursor, blockN1); + k5_iov_cursor_put(&cursor, blockN2); + + return 0; +} + +krb5_error_code +krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data, + size_t num_data, const krb5_data *ivec, + krb5_data *output) +{ + unsigned char iv[BLOCK_SIZE], block[BLOCK_SIZE]; + struct iov_cursor cursor; + + if (output->length < BLOCK_SIZE) + return KRB5_BAD_MSIZE; + + if (init_key_cache(key)) + return ENOMEM; + expand_enc_key(key); + + if (ivec != NULL) + memcpy(iv, ivec->data, BLOCK_SIZE); + else + memset(iv, 0, BLOCK_SIZE); + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + while (k5_iov_cursor_get(&cursor, block)) + cbc_enc(key, block, 1, iv); + + output->length = BLOCK_SIZE; + memcpy(output->data, iv, BLOCK_SIZE); + + return 0; +} + +static krb5_error_code +camellia_init_state(const krb5_keyblock *key, krb5_keyusage usage, + krb5_data *state) +{ + state->length = 16; + state->data = malloc(16); + if (state->data == NULL) + return ENOMEM; + memset(state->data, 0, state->length); + return 0; +} + +static void +camellia_key_cleanup(krb5_key key) +{ + zapfree(key->cache, sizeof(struct camellia_key_info_cache)); +} + +const struct krb5_enc_provider krb5int_enc_camellia128 = { + 16, + 16, 16, + krb5int_camellia_encrypt, + krb5int_camellia_decrypt, + krb5int_camellia_cbc_mac, + camellia_init_state, + krb5int_default_free_state, + camellia_key_cleanup +}; + +const struct krb5_enc_provider krb5int_enc_camellia256 = { + 16, + 32, 32, + krb5int_camellia_encrypt, + krb5int_camellia_decrypt, + krb5int_camellia_cbc_mac, + camellia_init_state, + krb5int_default_free_state, + camellia_key_cleanup +}; diff --git a/src/lib/crypto/builtin/enc_provider/deps b/src/lib/crypto/builtin/enc_provider/deps new file mode 100644 index 000000000000..72e34076684c --- /dev/null +++ b/src/lib/crypto/builtin/enc_provider/deps @@ -0,0 +1,64 @@ +# +# Generated makefile dependencies follow. +# +des.so des.po $(OUTPRE)des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../des/des_int.h \ + $(srcdir)/../sha2/sha2.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des.c +des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../des/des_int.h \ + $(srcdir)/../sha2/sha2.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des3.c +aes.so aes.po $(OUTPRE)aes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + aes.c +camellia.so camellia.po $(OUTPRE)camellia.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../aes/aes.h \ + $(srcdir)/../camellia/camellia.h $(srcdir)/../crypto_mod.h \ + $(srcdir)/../sha2/sha2.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h camellia.c +rc4.so rc4.po $(OUTPRE)rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(srcdir)/../aes/aes.h $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + rc4.c diff --git a/src/lib/crypto/builtin/enc_provider/des.c b/src/lib/crypto/builtin/enc_provider/des.c new file mode 100644 index 000000000000..30b8229f8c6f --- /dev/null +++ b/src/lib/crypto/builtin/enc_provider/des.c @@ -0,0 +1,120 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" +#include "des_int.h" + +static krb5_error_code +validate_and_schedule(krb5_key key, const krb5_data *ivec, + const krb5_crypto_iov *data, size_t num_data, + mit_des_key_schedule schedule) +{ + if (key->keyblock.length != 8) + return KRB5_BAD_KEYSIZE; + if (iov_total_length(data, num_data, FALSE) % 8 != 0) + return KRB5_BAD_MSIZE; + if (ivec != NULL && ivec->length != 8) + return KRB5_BAD_MSIZE; + + switch (mit_des_key_sched(key->keyblock.contents, schedule)) { + case -1: + return(KRB5DES_BAD_KEYPAR); + case -2: + return(KRB5DES_WEAK_KEY); + } + return 0; +} + +static krb5_error_code +des_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + mit_des_key_schedule schedule; + krb5_error_code err; + + err = validate_and_schedule(key, ivec, data, num_data, schedule); + if (err) + return err; + + krb5int_des_cbc_encrypt(data, num_data, schedule, + ivec != NULL ? (unsigned char *) ivec->data : + NULL); + + zap(schedule, sizeof(schedule)); + return 0; +} + +static krb5_error_code +des_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + mit_des_key_schedule schedule; + krb5_error_code err; + + err = validate_and_schedule(key, ivec, data, num_data, schedule); + if (err) + return err; + + krb5int_des_cbc_decrypt(data, num_data, schedule, + ivec != NULL ? (unsigned char *) ivec->data : + NULL); + + zap(schedule, sizeof(schedule)); + return 0; +} + +static krb5_error_code +des_cbc_mac(krb5_key key, const krb5_crypto_iov *data, size_t num_data, + const krb5_data *ivec, krb5_data *output) +{ + mit_des_key_schedule schedule; + krb5_error_code err; + + err = validate_and_schedule(key, ivec, data, num_data, schedule); + if (err) + return err; + + if (output->length != 8) + return KRB5_CRYPTO_INTERNAL; + + krb5int_des_cbc_mac(data, num_data, schedule, + ivec != NULL ? (unsigned char *) ivec->data : NULL, + (unsigned char *) output->data); + + zap(schedule, sizeof(schedule)); + return 0; +} + +const struct krb5_enc_provider krb5int_enc_des = { + 8, + 7, 8, + des_encrypt, + des_decrypt, + des_cbc_mac, + krb5int_des_init_state, + krb5int_default_free_state +}; diff --git a/src/lib/crypto/builtin/enc_provider/des3.c b/src/lib/crypto/builtin/enc_provider/des3.c new file mode 100644 index 000000000000..9b82442236f8 --- /dev/null +++ b/src/lib/crypto/builtin/enc_provider/des3.c @@ -0,0 +1,105 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" +#include "des_int.h" + +static krb5_error_code +validate_and_schedule(krb5_key key, const krb5_data *ivec, + const krb5_crypto_iov *data, size_t num_data, + mit_des3_key_schedule *schedule) +{ + if (key->keyblock.length != 24) + return(KRB5_BAD_KEYSIZE); + if (iov_total_length(data, num_data, FALSE) % 8 != 0) + return(KRB5_BAD_MSIZE); + if (ivec && (ivec->length != 8)) + return(KRB5_BAD_MSIZE); + + switch (mit_des3_key_sched(*(mit_des3_cblock *)key->keyblock.contents, + *schedule)) { + case -1: + return(KRB5DES_BAD_KEYPAR); + case -2: + return(KRB5DES_WEAK_KEY); + } + return 0; +} + +static krb5_error_code +k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + mit_des3_key_schedule schedule; + krb5_error_code err; + + err = validate_and_schedule(key, ivec, data, num_data, &schedule); + if (err) + return err; + + /* this has a return value, but the code always returns zero */ + krb5int_des3_cbc_encrypt(data, num_data, + schedule[0], schedule[1], schedule[2], + ivec != NULL ? (unsigned char *) ivec->data : + NULL); + + zap(schedule, sizeof(schedule)); + + return(0); +} + +static krb5_error_code +k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + mit_des3_key_schedule schedule; + krb5_error_code err; + + err = validate_and_schedule(key, ivec, data, num_data, &schedule); + if (err) + return err; + + /* this has a return value, but the code always returns zero */ + krb5int_des3_cbc_decrypt(data, num_data, + schedule[0], schedule[1], schedule[2], + ivec != NULL ? (unsigned char *) ivec->data : + NULL); + + zap(schedule, sizeof(schedule)); + + return 0; +} + +const struct krb5_enc_provider krb5int_enc_des3 = { + 8, + 21, 24, + k5_des3_encrypt, + k5_des3_decrypt, + NULL, + krb5int_des_init_state, + krb5int_default_free_state +}; diff --git a/src/lib/crypto/builtin/enc_provider/rc4.c b/src/lib/crypto/builtin/enc_provider/rc4.c new file mode 100644 index 000000000000..3776f80715ab --- /dev/null +++ b/src/lib/crypto/builtin/enc_provider/rc4.c @@ -0,0 +1,190 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/enc_provider/rc4.c */ +/* + * Copyright (c) 2000 by Computer Science Laboratory, + * Rensselaer Polytechnic Institute + * + * #include STD_DISCLAIMER + */ + +#include "crypto_int.h" + +typedef struct +{ + unsigned int x; + unsigned int y; + unsigned char state[256]; +} ArcfourContext; + +typedef struct { + int initialized; + ArcfourContext ctx; +} ArcFourCipherState; + +/* gets the next byte from the PRNG */ +#if ((__GNUC__ >= 2) ) +static __inline__ unsigned int k5_arcfour_byte(ArcfourContext *); +#else +static unsigned int k5_arcfour_byte(ArcfourContext *); +#endif /* gcc inlines*/ + +/* Initializes the context and sets the key. */ +static krb5_error_code k5_arcfour_init(ArcfourContext *ctx, const unsigned char *key, + unsigned int keylen); + +/* Encrypts/decrypts data. */ +static void k5_arcfour_crypt(ArcfourContext *ctx, unsigned char *dest, + const unsigned char *src, unsigned int len); + +static inline unsigned int k5_arcfour_byte(ArcfourContext * ctx) +{ + unsigned int x; + unsigned int y; + unsigned int sx, sy; + unsigned char *state; + + state = ctx->state; + x = (ctx->x + 1) & 0xff; + sx = state[x]; + y = (sx + ctx->y) & 0xff; + sy = state[y]; + ctx->x = x; + ctx->y = y; + state[y] = sx; + state[x] = sy; + return state[(sx + sy) & 0xff]; +} + +static void k5_arcfour_crypt(ArcfourContext *ctx, unsigned char *dest, + const unsigned char *src, unsigned int len) +{ + unsigned int i; + for (i = 0; i < len; i++) + dest[i] = src[i] ^ k5_arcfour_byte(ctx); +} + + +static krb5_error_code +k5_arcfour_init(ArcfourContext *ctx, const unsigned char *key, + unsigned int key_len) +{ + unsigned int t, u; + unsigned int keyindex; + unsigned int stateindex; + unsigned char* state; + unsigned int counter; + + if (key_len != 16) + return KRB5_BAD_MSIZE; /*this is probably not the correct error code + to return */ + state = &ctx->state[0]; + ctx->x = 0; + ctx->y = 0; + for (counter = 0; counter < 256; counter++) + state[counter] = counter; + keyindex = 0; + stateindex = 0; + for (counter = 0; counter < 256; counter++) + { + t = state[counter]; + stateindex = (stateindex + key[keyindex] + t) & 0xff; + u = state[stateindex]; + state[stateindex] = t; + state[counter] = u; + if (++keyindex >= key_len) + keyindex = 0; + } + return 0; +} + + +static krb5_error_code +k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data, + size_t num_data) +{ + ArcfourContext *arcfour_ctx = NULL; + ArcFourCipherState *cipher_state = NULL; + krb5_error_code ret; + size_t i; + + if (key->keyblock.length != 16) + return KRB5_BAD_KEYSIZE; + if (state != NULL && (state->length != sizeof(ArcFourCipherState))) + return KRB5_BAD_MSIZE; + + if (state != NULL) { + cipher_state = (ArcFourCipherState *)state->data; + arcfour_ctx = &cipher_state->ctx; + if (cipher_state->initialized == 0) { + ret = k5_arcfour_init(arcfour_ctx, key->keyblock.contents, + key->keyblock.length); + if (ret != 0) + return ret; + + cipher_state->initialized = 1; + } + } else { + arcfour_ctx = (ArcfourContext *)malloc(sizeof(ArcfourContext)); + if (arcfour_ctx == NULL) + return ENOMEM; + + ret = k5_arcfour_init(arcfour_ctx, key->keyblock.contents, + key->keyblock.length); + if (ret != 0) { + free(arcfour_ctx); + return ret; + } + } + + for (i = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_IOV(iov)) + k5_arcfour_crypt(arcfour_ctx, (unsigned char *)iov->data.data, + (const unsigned char *)iov->data.data, iov->data.length); + } + + if (state == NULL) + zapfree(arcfour_ctx, sizeof(ArcfourContext)); + + return 0; +} + +static krb5_error_code +k5_arcfour_init_state (const krb5_keyblock *key, + krb5_keyusage keyusage, krb5_data *new_state) +{ + /* Note that we can't actually set up the state here because the key + * will change between now and when encrypt is called + * because it is data dependent. Yeah, this has strange + * properties. --SDH + */ + new_state->length = sizeof (ArcFourCipherState); + new_state->data = malloc (new_state->length); + if (new_state->data) { + memset (new_state->data, 0 , new_state->length); + /* That will set initialized to zero*/ + }else { + return (ENOMEM); + } + return 0; +} + +/* Since the arcfour cipher is identical going forwards and backwards, + we just call "docrypt" directly +*/ +const struct krb5_enc_provider krb5int_enc_arcfour = { + /* This seems to work... although I am not sure what the + implications are in other places in the kerberos library */ + 1, + /* Keysize is arbitrary in arcfour, but the constraints of the + system, and to attempt to work with the MSFT system forces us + to 16byte/128bit. Since there is no parity in the key, the + byte and length are the same. */ + 16, 16, + k5_arcfour_docrypt, + k5_arcfour_docrypt, + NULL, + k5_arcfour_init_state, /*xxx not implemented yet*/ + krb5int_default_free_state +}; diff --git a/src/lib/crypto/builtin/hash_provider/Makefile.in b/src/lib/crypto/builtin/hash_provider/Makefile.in new file mode 100644 index 000000000000..2f587a497a72 --- /dev/null +++ b/src/lib/crypto/builtin/hash_provider/Makefile.in @@ -0,0 +1,40 @@ +mydir=lib$(S)crypto$(S)builtin$(S)hash_provider +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../krb -I$(srcdir)/../md4 \ + -I$(srcdir)/../md5 -I$(srcdir)/../sha1 -I$(srcdir)/../sha2 + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\hash_provider +##DOS##OBJFILE = ..\..\$(OUTPRE)hash_provider.lst + +STLIBOBJS= \ + hash_crc32.o \ + hash_md4.o \ + hash_md5.o \ + hash_sha1.o \ + hash_sha2.o + +OBJS= $(OUTPRE)hash_crc32.$(OBJEXT) \ + $(OUTPRE)hash_md4.$(OBJEXT) \ + $(OUTPRE)hash_md5.$(OBJEXT) \ + $(OUTPRE)hash_sha1.$(OBJEXT) \ + $(OUTPRE)hash_sha2.$(OBJEXT) + +SRCS= $(srcdir)/hash_crc32.c \ + $(srcdir)/hash_md4.c \ + $(srcdir)/hash_md5.c \ + $(srcdir)/hash_sha1.c \ + $(srcdir)/hash_sha2.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/src/lib/crypto/builtin/hash_provider/deps b/src/lib/crypto/builtin/hash_provider/deps new file mode 100644 index 000000000000..18f89b383cea --- /dev/null +++ b/src/lib/crypto/builtin/hash_provider/deps @@ -0,0 +1,68 @@ +# +# Generated makefile dependencies follow. +# +hash_crc32.so hash_crc32.po $(OUTPRE)hash_crc32.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../aes/aes.h \ + $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hash_crc32.c +hash_md4.so hash_md4.po $(OUTPRE)hash_md4.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../aes/aes.h \ + $(srcdir)/../crypto_mod.h $(srcdir)/../md4/rsa-md4.h \ + $(srcdir)/../sha2/sha2.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h hash_md4.c +hash_md5.so hash_md5.po $(OUTPRE)hash_md5.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../aes/aes.h \ + $(srcdir)/../crypto_mod.h $(srcdir)/../md5/rsa-md5.h \ + $(srcdir)/../sha2/sha2.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h hash_md5.c +hash_sha1.so hash_sha1.po $(OUTPRE)hash_sha1.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../aes/aes.h \ + $(srcdir)/../crypto_mod.h $(srcdir)/../sha1/shs.h $(srcdir)/../sha2/sha2.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hash_sha1.c +hash_sha2.so hash_sha2.po $(OUTPRE)hash_sha2.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../aes/aes.h \ + $(srcdir)/../crypto_mod.h $(srcdir)/../sha2/sha2.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hash_sha2.c diff --git a/src/lib/crypto/builtin/hash_provider/hash_crc32.c b/src/lib/crypto/builtin/hash_provider/hash_crc32.c new file mode 100644 index 000000000000..1d0be55637a9 --- /dev/null +++ b/src/lib/crypto/builtin/hash_provider/hash_crc32.c @@ -0,0 +1,56 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +static krb5_error_code +k5_crc32_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + unsigned long c; + unsigned int i; + + if (output->length != CRC32_CKSUM_LENGTH) + return KRB5_CRYPTO_INTERNAL; + + c = 0; + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) + mit_crc32(iov->data.data, iov->data.length, &c); + } + + store_32_le(c, output->data); + return 0; +} + +const struct krb5_hash_provider krb5int_hash_crc32 = { + "CRC32", + CRC32_CKSUM_LENGTH, + 1, + k5_crc32_hash +}; diff --git a/src/lib/crypto/builtin/hash_provider/hash_md4.c b/src/lib/crypto/builtin/hash_provider/hash_md4.c new file mode 100644 index 000000000000..e7daf5277622 --- /dev/null +++ b/src/lib/crypto/builtin/hash_provider/hash_md4.c @@ -0,0 +1,61 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" +#include "rsa-md4.h" + +static krb5_error_code +k5_md4_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + krb5_MD4_CTX ctx; + unsigned int i; + + if (output->length != RSA_MD4_CKSUM_LENGTH) + return(KRB5_CRYPTO_INTERNAL); + + krb5int_MD4Init(&ctx); + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) { + krb5int_MD4Update(&ctx, (unsigned char *) iov->data.data, + iov->data.length); + } + } + krb5int_MD4Final(&ctx); + + memcpy(output->data, ctx.digest, RSA_MD4_CKSUM_LENGTH); + + return(0); +} + +const struct krb5_hash_provider krb5int_hash_md4 = { + "MD4", + RSA_MD4_CKSUM_LENGTH, + 64, + k5_md4_hash +}; diff --git a/src/lib/crypto/builtin/hash_provider/hash_md5.c b/src/lib/crypto/builtin/hash_provider/hash_md5.c new file mode 100644 index 000000000000..0f655ddae85c --- /dev/null +++ b/src/lib/crypto/builtin/hash_provider/hash_md5.c @@ -0,0 +1,61 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" +#include "rsa-md5.h" + +static krb5_error_code +k5_md5_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + krb5_MD5_CTX ctx; + unsigned int i; + + if (output->length != RSA_MD5_CKSUM_LENGTH) + return KRB5_CRYPTO_INTERNAL; + + krb5int_MD5Init(&ctx); + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) { + krb5int_MD5Update(&ctx, (unsigned char *) iov->data.data, + iov->data.length); + } + } + krb5int_MD5Final(&ctx); + + memcpy(output->data, ctx.digest, RSA_MD5_CKSUM_LENGTH); + + return 0; +} + +const struct krb5_hash_provider krb5int_hash_md5 = { + "MD5", + RSA_MD5_CKSUM_LENGTH, + 64, + k5_md5_hash +}; diff --git a/src/lib/crypto/builtin/hash_provider/hash_sha1.c b/src/lib/crypto/builtin/hash_provider/hash_sha1.c new file mode 100644 index 000000000000..535e8e584a95 --- /dev/null +++ b/src/lib/crypto/builtin/hash_provider/hash_sha1.c @@ -0,0 +1,62 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" +#include "shs.h" + +static krb5_error_code +k5_sha1_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + SHS_INFO ctx; + unsigned int i; + + if (output->length != SHS_DIGESTSIZE) + return KRB5_CRYPTO_INTERNAL; + + shsInit(&ctx); + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) { + shsUpdate(&ctx, (unsigned char *) iov->data.data, + iov->data.length); + } + } + shsFinal(&ctx); + + for (i = 0; i < sizeof(ctx.digest) / sizeof(ctx.digest[0]); i++) + store_32_be(ctx.digest[i], &output->data[i*4]); + + return 0; +} + +const struct krb5_hash_provider krb5int_hash_sha1 = { + "SHA1", + SHS_DIGESTSIZE, + SHS_DATASIZE, + k5_sha1_hash +}; diff --git a/src/lib/crypto/builtin/hash_provider/hash_sha2.c b/src/lib/crypto/builtin/hash_provider/hash_sha2.c new file mode 100644 index 000000000000..ac4896d80e43 --- /dev/null +++ b/src/lib/crypto/builtin/hash_provider/hash_sha2.c @@ -0,0 +1,88 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/hash_provider/sha2.c - SHA-2 hash providers */ +/* + * Copyright (C) 2015 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "crypto_int.h" +#include "sha2.h" + +static krb5_error_code +k5_sha256_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + SHA256_CTX ctx; + size_t i; + const krb5_crypto_iov *iov; + + if (output->length != SHA256_DIGEST_LENGTH) + return KRB5_CRYPTO_INTERNAL; + + k5_sha256_init(&ctx); + for (i = 0; i < num_data; i++) { + iov = &data[i]; + if (SIGN_IOV(iov)) + k5_sha256_update(&ctx, iov->data.data, iov->data.length); + } + k5_sha256_final(output->data, &ctx); + return 0; +} + +static krb5_error_code +k5_sha384_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + SHA384_CTX ctx; + size_t i; + const krb5_crypto_iov *iov; + + if (output->length != SHA384_DIGEST_LENGTH) + return KRB5_CRYPTO_INTERNAL; + + k5_sha384_init(&ctx); + for (i = 0; i < num_data; i++) { + iov = &data[i]; + if (SIGN_IOV(iov)) + k5_sha384_update(&ctx, iov->data.data, iov->data.length); + } + k5_sha384_final(output->data, &ctx); + return 0; +} + +const struct krb5_hash_provider krb5int_hash_sha256 = { + "SHA-256", + SHA256_DIGEST_LENGTH, + SHA256_BLOCK_SIZE, + k5_sha256_hash +}; + +const struct krb5_hash_provider krb5int_hash_sha384 = { + "SHA-384", + SHA384_DIGEST_LENGTH, + SHA384_BLOCK_SIZE, + k5_sha384_hash +}; diff --git a/src/lib/crypto/builtin/hmac.c b/src/lib/crypto/builtin/hmac.c new file mode 100644 index 000000000000..95c8f5f4a0ea --- /dev/null +++ b/src/lib/crypto/builtin/hmac.c @@ -0,0 +1,120 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +/* + * Because our built-in HMAC implementation doesn't need to invoke any + * encryption or keyed hash functions, it is simplest to define it in terms of + * keyblocks, and then supply a simple wrapper for the "normal" krb5_key-using + * interfaces. The keyblock interfaces are useful for code which creates + * intermediate keyblocks. + */ + +/* + * The HMAC transform looks like: + * + * H(K XOR opad, H(K XOR ipad, text)) + * + * where H is a cryptographic hash + * K is an n byte key + * ipad is the byte 0x36 repeated blocksize times + * opad is the byte 0x5c repeated blocksize times + * and text is the data being protected + */ + +krb5_error_code +krb5int_hmac_keyblock(const struct krb5_hash_provider *hash, + const krb5_keyblock *keyblock, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + unsigned char *xorkey = NULL, *ihash = NULL; + unsigned int i; + krb5_crypto_iov *ihash_iov = NULL, ohash_iov[2]; + krb5_data hashout; + krb5_error_code ret; + + if (keyblock->length > hash->blocksize) + return KRB5_CRYPTO_INTERNAL; + if (output->length < hash->hashsize) + return KRB5_BAD_MSIZE; + + /* Allocate space for the xor key, hash input vector, and inner hash */ + xorkey = k5alloc(hash->blocksize, &ret); + if (xorkey == NULL) + goto cleanup; + ihash = k5alloc(hash->hashsize, &ret); + if (ihash == NULL) + goto cleanup; + ihash_iov = k5calloc(num_data + 1, sizeof(krb5_crypto_iov), &ret); + if (ihash_iov == NULL) + goto cleanup; + + /* Create the inner padded key. */ + memset(xorkey, 0x36, hash->blocksize); + for (i = 0; i < keyblock->length; i++) + xorkey[i] ^= keyblock->contents[i]; + + /* Compute the inner hash over the inner key and input data. */ + ihash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + ihash_iov[0].data = make_data(xorkey, hash->blocksize); + memcpy(ihash_iov + 1, data, num_data * sizeof(krb5_crypto_iov)); + hashout = make_data(ihash, hash->hashsize); + ret = hash->hash(ihash_iov, num_data + 1, &hashout); + if (ret != 0) + goto cleanup; + + /* Create the outer padded key. */ + memset(xorkey, 0x5c, hash->blocksize); + for (i = 0; i < keyblock->length; i++) + xorkey[i] ^= keyblock->contents[i]; + + /* Compute the outer hash over the outer key and inner hash value. */ + ohash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + ohash_iov[0].data = make_data(xorkey, hash->blocksize); + ohash_iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + ohash_iov[1].data = make_data(ihash, hash->hashsize); + output->length = hash->hashsize; + ret = hash->hash(ohash_iov, 2, output); + if (ret != 0) + memset(output->data, 0, output->length); + +cleanup: + zapfree(xorkey, hash->blocksize); + zapfree(ihash, hash->hashsize); + free(ihash_iov); + return ret; +} + +krb5_error_code +krb5int_hmac(const struct krb5_hash_provider *hash, krb5_key key, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + return krb5int_hmac_keyblock(hash, &key->keyblock, data, num_data, output); +} diff --git a/src/lib/crypto/builtin/init.c b/src/lib/crypto/builtin/init.c new file mode 100644 index 000000000000..b88d5deafa71 --- /dev/null +++ b/src/lib/crypto/builtin/init.c @@ -0,0 +1,38 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/init.c - Module init and cleanup functions */ +/* + * Copyright (C) 2010 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. + */ + +#include "crypto_int.h" + +int +krb5int_crypto_impl_init(void) +{ + return 0; +} + +void +krb5int_crypto_impl_cleanup(void) +{ +} diff --git a/src/lib/crypto/builtin/md4/ISSUES b/src/lib/crypto/builtin/md4/ISSUES new file mode 100644 index 000000000000..c343d290269d --- /dev/null +++ b/src/lib/crypto/builtin/md4/ISSUES @@ -0,0 +1,4 @@ +Issues to be addressed for src/lib/crypto/md4: -*- text -*- + + +Assumes int is >= 32 bits. diff --git a/src/lib/crypto/builtin/md4/Makefile.in b/src/lib/crypto/builtin/md4/Makefile.in new file mode 100644 index 000000000000..9eb596521db5 --- /dev/null +++ b/src/lib/crypto/builtin/md4/Makefile.in @@ -0,0 +1,33 @@ +mydir=lib$(S)crypto$(S)builtin$(S)md4 +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir) + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\md4 +##DOS##OBJFILE = ..\..\$(OUTPRE)md4.lst + +STLIBOBJS= md4.o + +OBJS= $(OUTPRE)md4.$(OBJEXT) + +SRCS= $(srcdir)/md4.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + + +check-unix: + +check-windows: + +clean: + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/src/lib/crypto/builtin/md4/deps b/src/lib/crypto/builtin/md4/deps new file mode 100644 index 000000000000..55d209b453d6 --- /dev/null +++ b/src/lib/crypto/builtin/md4/deps @@ -0,0 +1,13 @@ +# +# Generated makefile dependencies follow. +# +md4.so md4.po $(OUTPRE)md4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h md4.c rsa-md4.h diff --git a/src/lib/crypto/builtin/md4/md4.c b/src/lib/crypto/builtin/md4/md4.c new file mode 100644 index 000000000000..27d2ad514899 --- /dev/null +++ b/src/lib/crypto/builtin/md4/md4.c @@ -0,0 +1,243 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/md4/md4.c */ + +/* + * Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + * + * License to copy and use this software is granted provided that + * it is identified as the "RSA Data Security, Inc. MD4 Message + * Digest Algorithm" in all material mentioning or referencing this + * software or this function. + * + * License is also granted to make and use derivative works + * provided that such works are identified as "derived from the RSA + * Data Security, Inc. MD4 Message Digest Algorithm" in all + * material mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning + * either the merchantability of this software or the suitability + * of this software for any particular purpose. It is provided "as + * is" without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +/* +********************************************************************** +** md4.c ** +** RSA Data Security, Inc. MD4 Message Digest Algorithm ** +** Created: 2/17/90 RLR ** +** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** +********************************************************************** +*/ + +#include "k5-int.h" +#include "rsa-md4.h" + +/* forward declaration */ +static void Transform (krb5_ui_4 *, krb5_ui_4 *); + +static const unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G and H are basic MD4 functions: selection, majority, parity */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) ((((x) << (n)) & 0xffffffff) | ((x) >> (32-(n)))) + +/* FF, GG and HH are MD4 transformations for rounds 1, 2 and 3 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s) \ + {(a) += F ((b), (c), (d)) + (x); \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s));} +#define GG(a, b, c, d, x, s) \ + {(a) += G ((b), (c), (d)) + (x) + 013240474631UL; \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s));} +#define HH(a, b, c, d, x, s) \ + {(a) += H ((b), (c), (d)) + (x) + 015666365641UL; \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s));} + +void +krb5int_MD4Init (krb5_MD4_CTX *mdContext) +{ + mdContext->i[0] = mdContext->i[1] = (krb5_ui_4)0; + + /* Load magic initialization constants. + */ + mdContext->buf[0] = 0x67452301UL; + mdContext->buf[1] = 0xefcdab89UL; + mdContext->buf[2] = 0x98badcfeUL; + mdContext->buf[3] = 0x10325476UL; +} + +void +krb5int_MD4Update (krb5_MD4_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen) +{ + krb5_ui_4 in[16]; + int mdi; + unsigned int i, ii; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((krb5_ui_4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + mdContext->i[0] += ((krb5_ui_4)inLen << 3); + mdContext->i[1] += ((krb5_ui_4)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) { + in[i] = load_32_le(mdContext->in+ii); + } + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +void +krb5int_MD4Final (krb5_MD4_CTX *mdContext) +{ + krb5_ui_4 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + krb5int_MD4Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = load_32_le(mdContext->in+ii); + Transform (mdContext->buf, in); + + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + store_32_le(mdContext->buf[i], mdContext->digest+ii); + } +} + +/* Basic MD4 step. Transform buf based on in. + */ +static void Transform (krb5_ui_4 *buf, krb5_ui_4 *in) +{ + register krb5_ui_4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) + int i; +#define ROTATE { krb5_ui_4 temp; temp = d, d = c, c = b, b = a, a = temp; } + for (i = 0; i < 16; i++) { + static const unsigned char round1consts[] = { 3, 7, 11, 19, }; + FF (a, b, c, d, in[i], round1consts[i%4]); ROTATE; + } + for (i = 0; i < 16; i++) { + static const unsigned char round2indices[] = { + 0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15 + }; + static const unsigned char round2consts[] = { 3, 5, 9, 13 }; + GG (a, b, c, d, in[round2indices[i]], round2consts[i%4]); ROTATE; + } + for (i = 0; i < 16; i++) { + static const unsigned char round3indices[] = { + 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 + }; + static const unsigned char round3consts[] = { 3, 9, 11, 15 }; + HH (a, b, c, d, in[round3indices[i]], round3consts[i%4]); ROTATE; + } +#else + /* Round 1 */ + FF (a, b, c, d, in[ 0], 3); + FF (d, a, b, c, in[ 1], 7); + FF (c, d, a, b, in[ 2], 11); + FF (b, c, d, a, in[ 3], 19); + FF (a, b, c, d, in[ 4], 3); + FF (d, a, b, c, in[ 5], 7); + FF (c, d, a, b, in[ 6], 11); + FF (b, c, d, a, in[ 7], 19); + FF (a, b, c, d, in[ 8], 3); + FF (d, a, b, c, in[ 9], 7); + FF (c, d, a, b, in[10], 11); + FF (b, c, d, a, in[11], 19); + FF (a, b, c, d, in[12], 3); + FF (d, a, b, c, in[13], 7); + FF (c, d, a, b, in[14], 11); + FF (b, c, d, a, in[15], 19); + + /* Round 2 */ + GG (a, b, c, d, in[ 0], 3); + GG (d, a, b, c, in[ 4], 5); + GG (c, d, a, b, in[ 8], 9); + GG (b, c, d, a, in[12], 13); + GG (a, b, c, d, in[ 1], 3); + GG (d, a, b, c, in[ 5], 5); + GG (c, d, a, b, in[ 9], 9); + GG (b, c, d, a, in[13], 13); + GG (a, b, c, d, in[ 2], 3); + GG (d, a, b, c, in[ 6], 5); + GG (c, d, a, b, in[10], 9); + GG (b, c, d, a, in[14], 13); + GG (a, b, c, d, in[ 3], 3); + GG (d, a, b, c, in[ 7], 5); + GG (c, d, a, b, in[11], 9); + GG (b, c, d, a, in[15], 13); + + /* Round 3 */ + HH (a, b, c, d, in[ 0], 3); + HH (d, a, b, c, in[ 8], 9); + HH (c, d, a, b, in[ 4], 11); + HH (b, c, d, a, in[12], 15); + HH (a, b, c, d, in[ 2], 3); + HH (d, a, b, c, in[10], 9); + HH (c, d, a, b, in[ 6], 11); + HH (b, c, d, a, in[14], 15); + HH (a, b, c, d, in[ 1], 3); + HH (d, a, b, c, in[ 9], 9); + HH (c, d, a, b, in[ 5], 11); + HH (b, c, d, a, in[13], 15); + HH (a, b, c, d, in[ 3], 3); + HH (d, a, b, c, in[11], 9); + HH (c, d, a, b, in[ 7], 11); + HH (b, c, d, a, in[15], 15); +#endif + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* +********************************************************************** +** End of md4.c ** +******************************* (cut) ******************************** +*/ diff --git a/src/lib/crypto/builtin/md4/rsa-md4.h b/src/lib/crypto/builtin/md4/rsa-md4.h new file mode 100644 index 000000000000..c404e151b9cd --- /dev/null +++ b/src/lib/crypto/builtin/md4/rsa-md4.h @@ -0,0 +1,90 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/md4/rsa-md4.h */ +/* + * Copyright 1991 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. + */ +/* + * Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + * + * License to copy and use this software is granted provided that + * it is identified as the "RSA Data Security, Inc. MD4 Message + * Digest Algorithm" in all material mentioning or referencing this + * software or this function. + * + * License is also granted to make and use derivative works + * provided that such works are identified as "derived from the RSA + * Data Security, Inc. MD4 Message Digest Algorithm" in all + * material mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning + * either the merchantability of this software or the suitability + * of this software for any particular purpose. It is provided "as + * is" without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +/* RSA MD4 header file, with Kerberos/STDC additions. */ + +#ifndef __KRB5_RSA_MD4_H__ +#define __KRB5_RSA_MD4_H__ + +#ifdef unicos61 +#include <sys/types.h> +#endif /* unicos61 */ + +/* 16 u_char's in the digest */ +#define RSA_MD4_CKSUM_LENGTH 16 +/* des blocksize is 8, so this works nicely... */ +#define OLD_RSA_MD4_DES_CKSUM_LENGTH 16 +#define NEW_RSA_MD4_DES_CKSUM_LENGTH 24 +#define RSA_MD4_DES_CONFOUND_LENGTH 8 + +/* +********************************************************************** +** md4.h -- Header file for implementation of MD4 ** +** RSA Data Security, Inc. MD4 Message Digest Algorithm ** +** Created: 2/17/90 RLR ** +** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** +********************************************************************** +*/ + +/* Data structure for MD4 (Message Digest) computation */ +typedef struct { + krb5_ui_4 i[2]; /* number of _bits_ handled mod 2^64 */ + krb5_ui_4 buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD4Final call */ +} krb5_MD4_CTX; + +extern void krb5int_MD4Init(krb5_MD4_CTX *); +extern void krb5int_MD4Update(krb5_MD4_CTX *, const unsigned char *, unsigned int); +extern void krb5int_MD4Final(krb5_MD4_CTX *); + +/* +********************************************************************** +** End of md4.h ** +******************************* (cut) ******************************** +*/ +#endif /* __KRB5_RSA_MD4_H__ */ diff --git a/src/lib/crypto/builtin/md5/ISSUES b/src/lib/crypto/builtin/md5/ISSUES new file mode 100644 index 000000000000..631238adfb04 --- /dev/null +++ b/src/lib/crypto/builtin/md5/ISSUES @@ -0,0 +1,4 @@ +Issues to be addressed for src/lib/crypto/md5: -*- text -*- + + +Assumes int is >= 32 bits. diff --git a/src/lib/crypto/builtin/md5/Makefile.in b/src/lib/crypto/builtin/md5/Makefile.in new file mode 100644 index 000000000000..e8778f380ca3 --- /dev/null +++ b/src/lib/crypto/builtin/md5/Makefile.in @@ -0,0 +1,31 @@ +mydir=lib$(S)crypto$(S)builtin$(S)md5 +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\md5 +##DOS##OBJFILE = ..\..\$(OUTPRE)md5.lst + +STLIBOBJS= md5.o + +OBJS= $(OUTPRE)md5.$(OBJEXT) + +SRCS= $(srcdir)/md5.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + +check-unix: + +check-windows: + +clean: + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/src/lib/crypto/builtin/md5/deps b/src/lib/crypto/builtin/md5/deps new file mode 100644 index 000000000000..31840880f3a2 --- /dev/null +++ b/src/lib/crypto/builtin/md5/deps @@ -0,0 +1,13 @@ +# +# Generated makefile dependencies follow. +# +md5.so md5.po $(OUTPRE)md5.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h md5.c rsa-md5.h diff --git a/src/lib/crypto/builtin/md5/md5.c b/src/lib/crypto/builtin/md5/md5.c new file mode 100644 index 000000000000..4a169065cd0d --- /dev/null +++ b/src/lib/crypto/builtin/md5/md5.c @@ -0,0 +1,342 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + * + * License to copy and use this software is granted provided that + * it is identified as the "RSA Data Security, Inc. MD5 Message- + * Digest Algorithm" in all material mentioning or referencing this + * software or this function. + * + * License is also granted to make and use derivative works + * provided that such works are identified as "derived from the RSA + * Data Security, Inc. MD5 Message-Digest Algorithm" in all + * material mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning + * either the merchantability of this software or the suitability + * of this software for any particular purpose. It is provided "as + * is" without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +/* +*********************************************************************** +** md5.c -- the source code for MD5 routines ** +** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** +** Created: 2/17/90 RLR ** +** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** +*********************************************************************** +*/ + +/* + * Modified by John Carr, MIT, to use Kerberos 5 typedefs. + */ + +#include "k5-int.h" +#include "rsa-md5.h" + +/* +*********************************************************************** +** Message-digest routines: ** +** To form the message digest for a message M ** +** (1) Initialize a context buffer mdContext using krb5int_MD5Init ** +** (2) Call krb5int_MD5Update on mdContext and M ** +** (3) Call krb5int_MD5Final on mdContext ** +** The message digest is now in mdContext->digest[0...15] ** +*********************************************************************** +*/ + +/* forward declaration */ +static void Transform (krb5_ui_4 *buf, krb5_ui_4 *in); + +static const unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G, H and I are basic MD5 functions */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) ((((x) << (n)) & 0xffffffff) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + (a) &= 0xffffffff; \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + (a) &= 0xffffffff; \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + (a) &= 0xffffffff; \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + (a) &= 0xffffffff; \ + } + +/* The routine krb5int_MD5Init initializes the message-digest context + mdContext. All fields are set to zero. +*/ +void +krb5int_MD5Init (krb5_MD5_CTX *mdContext) +{ + mdContext->i[0] = mdContext->i[1] = (krb5_ui_4)0; + + /* Load magic initialization constants. + */ + mdContext->buf[0] = 0x67452301UL; + mdContext->buf[1] = 0xefcdab89UL; + mdContext->buf[2] = 0x98badcfeUL; + mdContext->buf[3] = 0x10325476UL; +} + +/* The routine krb5int_MD5Update updates the message-digest context to + account for the presence of each of the characters inBuf[0..inLen-1] + in the message whose digest is being computed. +*/ +void +krb5int_MD5Update (krb5_MD5_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen) +{ + krb5_ui_4 in[16]; + int mdi; + unsigned int i, ii; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((krb5_ui_4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + mdContext->i[0] += ((krb5_ui_4)inLen << 3); + mdContext->i[1] += ((krb5_ui_4)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = load_32_le(mdContext->in+ii); + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +/* The routine krb5int_MD5Final terminates the message-digest computation and + ends with the desired message digest in mdContext->digest[0...15]. +*/ +void +krb5int_MD5Final (krb5_MD5_CTX *mdContext) +{ + krb5_ui_4 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + krb5int_MD5Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = load_32_le(mdContext->in+ii); + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + store_32_le(mdContext->buf[i], mdContext->digest+ii); + } +} + +/* Basic MD5 step. Transforms buf based on in. + */ +static void Transform (krb5_ui_4 *buf, krb5_ui_4 *in) +{ + register krb5_ui_4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) + + int i; +#define ROTATE { krb5_ui_4 temp; temp = d, d = c, c = b, b = a, a = temp; } + for (i = 0; i < 16; i++) { + const unsigned char round1s[] = { 7, 12, 17, 22 }; + const krb5_ui_4 round1consts[] = { + 3614090360UL, 3905402710UL, 606105819UL, 3250441966UL, + 4118548399UL, 1200080426UL, 2821735955UL, 4249261313UL, + 1770035416UL, 2336552879UL, 4294925233UL, 2304563134UL, + 1804603682UL, 4254626195UL, 2792965006UL, 1236535329UL, + }; + FF (a, b, c, d, in[i], round1s[i%4], round1consts[i]); + ROTATE; + } + for (i = 0; i < 16; i++) { + const unsigned char round2s[] = { 5, 9, 14, 20 }; + const krb5_ui_4 round2consts[] = { + 4129170786UL, 3225465664UL, 643717713UL, 3921069994UL, + 3593408605UL, 38016083UL, 3634488961UL, 3889429448UL, + 568446438UL, 3275163606UL, 4107603335UL, 1163531501UL, + 2850285829UL, 4243563512UL, 1735328473UL, 2368359562UL, + }; + int r2index = (1 + i * 5) % 16; + GG (a, b, c, d, in[r2index], round2s[i%4], round2consts[i]); + ROTATE; + } + for (i = 0; i < 16; i++) { + static const unsigned char round3s[] = { 4, 11, 16, 23 }; + static const krb5_ui_4 round3consts[] = { + 4294588738UL, 2272392833UL, 1839030562UL, 4259657740UL, + 2763975236UL, 1272893353UL, 4139469664UL, 3200236656UL, + 681279174UL, 3936430074UL, 3572445317UL, 76029189UL, + 3654602809UL, 3873151461UL, 530742520UL, 3299628645UL, + }; + int r3index = (5 + i * 3) % 16; + HH (a, b, c, d, in[r3index], round3s[i%4], round3consts[i]); + ROTATE; + } + for (i = 0; i < 16; i++) { + static const unsigned char round4s[] = { 6, 10, 15, 21 }; + static const krb5_ui_4 round4consts[] = { + 4096336452UL, 1126891415UL, 2878612391UL, 4237533241UL, + 1700485571UL, 2399980690UL, 4293915773UL, 2240044497UL, + 1873313359UL, 4264355552UL, 2734768916UL, 1309151649UL, + 4149444226UL, 3174756917UL, 718787259UL, 3951481745UL, + }; + int r4index = (7 * i) % 16; + II (a, b, c, d, in[r4index], round4s[i%4], round4consts[i]); + ROTATE; + } + +#else + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF ( a, b, c, d, in[ 0], S11, 3614090360UL); /* 1 */ + FF ( d, a, b, c, in[ 1], S12, 3905402710UL); /* 2 */ + FF ( c, d, a, b, in[ 2], S13, 606105819UL); /* 3 */ + FF ( b, c, d, a, in[ 3], S14, 3250441966UL); /* 4 */ + FF ( a, b, c, d, in[ 4], S11, 4118548399UL); /* 5 */ + FF ( d, a, b, c, in[ 5], S12, 1200080426UL); /* 6 */ + FF ( c, d, a, b, in[ 6], S13, 2821735955UL); /* 7 */ + FF ( b, c, d, a, in[ 7], S14, 4249261313UL); /* 8 */ + FF ( a, b, c, d, in[ 8], S11, 1770035416UL); /* 9 */ + FF ( d, a, b, c, in[ 9], S12, 2336552879UL); /* 10 */ + FF ( c, d, a, b, in[10], S13, 4294925233UL); /* 11 */ + FF ( b, c, d, a, in[11], S14, 2304563134UL); /* 12 */ + FF ( a, b, c, d, in[12], S11, 1804603682UL); /* 13 */ + FF ( d, a, b, c, in[13], S12, 4254626195UL); /* 14 */ + FF ( c, d, a, b, in[14], S13, 2792965006UL); /* 15 */ + FF ( b, c, d, a, in[15], S14, 1236535329UL); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG ( a, b, c, d, in[ 1], S21, 4129170786UL); /* 17 */ + GG ( d, a, b, c, in[ 6], S22, 3225465664UL); /* 18 */ + GG ( c, d, a, b, in[11], S23, 643717713UL); /* 19 */ + GG ( b, c, d, a, in[ 0], S24, 3921069994UL); /* 20 */ + GG ( a, b, c, d, in[ 5], S21, 3593408605UL); /* 21 */ + GG ( d, a, b, c, in[10], S22, 38016083UL); /* 22 */ + GG ( c, d, a, b, in[15], S23, 3634488961UL); /* 23 */ + GG ( b, c, d, a, in[ 4], S24, 3889429448UL); /* 24 */ + GG ( a, b, c, d, in[ 9], S21, 568446438UL); /* 25 */ + GG ( d, a, b, c, in[14], S22, 3275163606UL); /* 26 */ + GG ( c, d, a, b, in[ 3], S23, 4107603335UL); /* 27 */ + GG ( b, c, d, a, in[ 8], S24, 1163531501UL); /* 28 */ + GG ( a, b, c, d, in[13], S21, 2850285829UL); /* 29 */ + GG ( d, a, b, c, in[ 2], S22, 4243563512UL); /* 30 */ + GG ( c, d, a, b, in[ 7], S23, 1735328473UL); /* 31 */ + GG ( b, c, d, a, in[12], S24, 2368359562UL); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH ( a, b, c, d, in[ 5], S31, 4294588738UL); /* 33 */ + HH ( d, a, b, c, in[ 8], S32, 2272392833UL); /* 34 */ + HH ( c, d, a, b, in[11], S33, 1839030562UL); /* 35 */ + HH ( b, c, d, a, in[14], S34, 4259657740UL); /* 36 */ + HH ( a, b, c, d, in[ 1], S31, 2763975236UL); /* 37 */ + HH ( d, a, b, c, in[ 4], S32, 1272893353UL); /* 38 */ + HH ( c, d, a, b, in[ 7], S33, 4139469664UL); /* 39 */ + HH ( b, c, d, a, in[10], S34, 3200236656UL); /* 40 */ + HH ( a, b, c, d, in[13], S31, 681279174UL); /* 41 */ + HH ( d, a, b, c, in[ 0], S32, 3936430074UL); /* 42 */ + HH ( c, d, a, b, in[ 3], S33, 3572445317UL); /* 43 */ + HH ( b, c, d, a, in[ 6], S34, 76029189UL); /* 44 */ + HH ( a, b, c, d, in[ 9], S31, 3654602809UL); /* 45 */ + HH ( d, a, b, c, in[12], S32, 3873151461UL); /* 46 */ + HH ( c, d, a, b, in[15], S33, 530742520UL); /* 47 */ + HH ( b, c, d, a, in[ 2], S34, 3299628645UL); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II ( a, b, c, d, in[ 0], S41, 4096336452UL); /* 49 */ + II ( d, a, b, c, in[ 7], S42, 1126891415UL); /* 50 */ + II ( c, d, a, b, in[14], S43, 2878612391UL); /* 51 */ + II ( b, c, d, a, in[ 5], S44, 4237533241UL); /* 52 */ + II ( a, b, c, d, in[12], S41, 1700485571UL); /* 53 */ + II ( d, a, b, c, in[ 3], S42, 2399980690UL); /* 54 */ + II ( c, d, a, b, in[10], S43, 4293915773UL); /* 55 */ + II ( b, c, d, a, in[ 1], S44, 2240044497UL); /* 56 */ + II ( a, b, c, d, in[ 8], S41, 1873313359UL); /* 57 */ + II ( d, a, b, c, in[15], S42, 4264355552UL); /* 58 */ + II ( c, d, a, b, in[ 6], S43, 2734768916UL); /* 59 */ + II ( b, c, d, a, in[13], S44, 1309151649UL); /* 60 */ + II ( a, b, c, d, in[ 4], S41, 4149444226UL); /* 61 */ + II ( d, a, b, c, in[11], S42, 3174756917UL); /* 62 */ + II ( c, d, a, b, in[ 2], S43, 718787259UL); /* 63 */ + II ( b, c, d, a, in[ 9], S44, 3951481745UL); /* 64 */ + +#endif /* small? */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} diff --git a/src/lib/crypto/builtin/md5/rsa-md5.h b/src/lib/crypto/builtin/md5/rsa-md5.h new file mode 100644 index 000000000000..cbdf67cfb333 --- /dev/null +++ b/src/lib/crypto/builtin/md5/rsa-md5.h @@ -0,0 +1,59 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + * + * License to copy and use this software is granted provided that + * it is identified as the "RSA Data Security, Inc. MD5 Message- + * Digest Algorithm" in all material mentioning or referencing this + * software or this function. + * + * License is also granted to make and use derivative works + * provided that such works are identified as "derived from the RSA + * Data Security, Inc. MD5 Message-Digest Algorithm" in all + * material mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning + * either the merchantability of this software or the suitability + * of this software for any particular purpose. It is provided "as + * is" without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +/* +*********************************************************************** +** md5.h -- header file for implementation of MD5 ** +** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** +** Created: 2/17/90 RLR ** +** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** +** Revised (for MD5): RLR 4/27/91 ** +** -- G modified to have y&~z instead of y&z ** +** -- FF, GG, HH modified to add in last register done ** +** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** +** -- distinct additive constant for each step ** +** -- round 4 added, working mod 7 ** +*********************************************************************** +*/ + +#ifndef KRB5_RSA_MD5__ +#define KRB5_RSA_MD5__ + +/* Data structure for MD5 (Message-Digest) computation */ +typedef struct { + krb5_ui_4 i[2]; /* number of _bits_ handled mod 2^64 */ + krb5_ui_4 buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD5Final call */ +} krb5_MD5_CTX; + +extern void krb5int_MD5Init(krb5_MD5_CTX *); +extern void krb5int_MD5Update(krb5_MD5_CTX *,const unsigned char *,unsigned int); +extern void krb5int_MD5Final(krb5_MD5_CTX *); + +#define RSA_MD5_CKSUM_LENGTH 16 +#define OLD_RSA_MD5_DES_CKSUM_LENGTH 16 +#define NEW_RSA_MD5_DES_CKSUM_LENGTH 24 +#define RSA_MD5_DES_CONFOUND_LENGTH 8 + +#endif /* KRB5_RSA_MD5__ */ diff --git a/src/lib/crypto/builtin/pbkdf2.c b/src/lib/crypto/builtin/pbkdf2.c new file mode 100644 index 000000000000..d36b32e7e3db --- /dev/null +++ b/src/lib/crypto/builtin/pbkdf2.c @@ -0,0 +1,249 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/pbkdf2.c - Implementation of PBKDF2 from RFC 2898 */ +/* + * Copyright 2002, 2008 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. + */ + +#include <ctype.h> +#include "crypto_int.h" + +/* + * RFC 2898 specifies PBKDF2 in terms of an underlying pseudo-random + * function with two arguments (password and salt||blockindex). Right + * now we only use PBKDF2 with the hmac-sha1 PRF, also specified in + * RFC 2898, which invokes HMAC with the password as the key and the + * second argument as the text. (HMAC accepts any key size up to the + * block size; the password is pre-hashed with unkeyed SHA1 if it is + * longer than the block size.) + * + * For efficiency, it is better to generate the key from the password + * once at the beginning, so we specify prf_fn in terms of a + * krb5_key first argument. That might not be convenient for a PRF + * which uses the password in some other way, so this might need to be + * adjusted in the future. + */ + +typedef krb5_error_code (*prf_fn)(krb5_key pass, krb5_data *salt, + krb5_data *out); + +static int debug_hmac = 0; + +static void printd (const char *descr, krb5_data *d) { + unsigned int i, j; + const int r = 16; + + printf("%s:", descr); + + for (i = 0; i < d->length; i += r) { + printf("\n %04x: ", i); + for (j = i; j < i + r && j < d->length; j++) + printf(" %02x", 0xff & d->data[j]); + for (; j < i + r; j++) + printf(" "); + printf(" "); + for (j = i; j < i + r && j < d->length; j++) { + int c = 0xff & d->data[j]; + printf("%c", isprint(c) ? c : '.'); + } + } + printf("\n"); +} + +/* + * Implements the hmac-sha1 PRF. pass has been pre-hashed (if + * necessary) and converted to a key already; salt has had the block + * index appended to the original salt. + */ +static krb5_error_code +hmac(const struct krb5_hash_provider *hash, krb5_keyblock *pass, + krb5_data *salt, krb5_data *out) +{ + krb5_error_code err; + krb5_crypto_iov iov; + + if (debug_hmac) + printd(" hmac input", salt); + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *salt; + err = krb5int_hmac_keyblock(hash, pass, &iov, 1, out); + if (err == 0 && debug_hmac) + printd(" hmac output", out); + return err; +} + +static krb5_error_code +F(char *output, char *u_tmp1, char *u_tmp2, + const struct krb5_hash_provider *hash, size_t hlen, krb5_keyblock *pass, + const krb5_data *salt, unsigned long count, int i) +{ + unsigned char ibytes[4]; + unsigned int j, k; + krb5_data sdata; + krb5_data out; + krb5_error_code err; + +#if 0 + printf("F(i=%d, count=%lu, pass=%d:%s)\n", i, count, + pass->length, pass->data); +#endif + + /* Compute U_1. */ + store_32_be(i, ibytes); + + memcpy(u_tmp2, salt->data, salt->length); + memcpy(u_tmp2 + salt->length, ibytes, 4); + sdata = make_data(u_tmp2, salt->length + 4); + +#if 0 + printd("initial salt", &sdata); +#endif + + out = make_data(u_tmp1, hlen); + +#if 0 + printf("F: computing hmac #1 (U_1) with %s\n", pdata.contents); +#endif + err = hmac(hash, pass, &sdata, &out); + if (err) + return err; +#if 0 + printd("F: prf return value", &out); +#endif + memcpy(output, u_tmp1, hlen); + + /* Compute U_2, .. U_c. */ + sdata.length = hlen; + for (j = 2; j <= count; j++) { +#if 0 + printf("F: computing hmac #%d (U_%d)\n", j, j); +#endif + memcpy(u_tmp2, u_tmp1, hlen); + err = hmac(hash, pass, &sdata, &out); + if (err) + return err; +#if 0 + printd("F: prf return value", &out); +#endif + /* And xor them together. */ + for (k = 0; k < hlen; k++) + output[k] ^= u_tmp1[k]; +#if 0 + printf("F: xor result:\n"); + for (k = 0; k < hlen; k++) + printf(" %02x", 0xff & output[k]); + printf("\n"); +#endif + } + return 0; +} + +static krb5_error_code +pbkdf2(const struct krb5_hash_provider *hash, krb5_keyblock *pass, + const krb5_data *salt, unsigned long count, const krb5_data *output) +{ + size_t hlen = hash->hashsize; + int l, i; + char *utmp1, *utmp2; + char utmp3[128]; /* XXX length shouldn't be hardcoded! */ + + if (output->length == 0 || hlen == 0) + abort(); + /* Step 1 & 2. */ + if (output->length / hlen > 0xffffffff) + abort(); + /* Step 2. */ + l = (output->length + hlen - 1) / hlen; + + utmp1 = /*output + dklen; */ malloc(hlen); + if (utmp1 == NULL) + return ENOMEM; + utmp2 = /*utmp1 + hlen; */ malloc(salt->length + 4 + hlen); + if (utmp2 == NULL) { + free(utmp1); + return ENOMEM; + } + + /* Step 3. */ + for (i = 1; i <= l; i++) { +#if 0 + int j; +#endif + krb5_error_code err; + char *out; + + if (i == l) + out = utmp3; + else + out = output->data + (i-1) * hlen; + err = F(out, utmp1, utmp2, hash, hlen, pass, salt, count, i); + if (err) { + free(utmp1); + free(utmp2); + return err; + } + if (i == l) + memcpy(output->data + (i-1) * hlen, utmp3, + output->length - (i-1) * hlen); + +#if 0 + printf("after F(%d), @%p:\n", i, output->data); + for (j = (i-1) * hlen; j < i * hlen; j++) + printf(" %02x", 0xff & output->data[j]); + printf ("\n"); +#endif + } + free(utmp1); + free(utmp2); + return 0; +} + +krb5_error_code +krb5int_pbkdf2_hmac(const struct krb5_hash_provider *hash, + const krb5_data *out, unsigned long count, + const krb5_data *pass, const krb5_data *salt) +{ + krb5_keyblock keyblock; + char tmp[128]; + krb5_data d; + krb5_crypto_iov iov; + krb5_error_code err; + + assert(hash->hashsize <= sizeof(tmp)); + if (pass->length > hash->blocksize) { + d = make_data(tmp, hash->hashsize); + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *pass; + err = hash->hash(&iov, 1, &d); + if (err) + return err; + keyblock.length = d.length; + keyblock.contents = (krb5_octet *) d.data; + } else { + keyblock.length = pass->length; + keyblock.contents = (krb5_octet *) pass->data; + } + keyblock.enctype = ENCTYPE_NULL; + + err = pbkdf2(hash, &keyblock, salt, count, out); + return err; +} diff --git a/src/lib/crypto/builtin/sha1/ISSUES b/src/lib/crypto/builtin/sha1/ISSUES new file mode 100644 index 000000000000..c63faf6e7a00 --- /dev/null +++ b/src/lib/crypto/builtin/sha1/ISSUES @@ -0,0 +1,8 @@ +Issues to be addressed for src/lib/crypto/sha1: -*- text -*- + + +Assumes int (look for "count") is >= 32 bits. + +Changing the types of internal variables is easy, but shsUpdate takes +an int parameter; changing that could change the ABI on some +platforms. diff --git a/src/lib/crypto/builtin/sha1/Makefile.in b/src/lib/crypto/builtin/sha1/Makefile.in new file mode 100644 index 000000000000..5895c364c65f --- /dev/null +++ b/src/lib/crypto/builtin/sha1/Makefile.in @@ -0,0 +1,44 @@ +mydir=lib$(S)crypto$(S)builtin$(S)sha1 +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\sha1 +##DOS##OBJFILE = ..\..\$(OUTPRE)sha1.lst + +STLIBOBJS= shs.o + +OBJS= $(OUTPRE)shs.$(OBJEXT) + +SRCS= $(srcdir)/shs.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) +t_shs: t_shs.o shs.o $(SUPPORT_DEPLIB) + $(CC_LINK) -o t_shs t_shs.o shs.o $(SUPPORT_LIB) + +$(OUTPRE)t_shs.exe: $(OUTPRE)t_shs.obj $(OUTPRE)shs.obj + link -out:$@ $** + +t_shs3: t_shs3.o shs.o $(SUPPORT_DEPLIB) + $(CC_LINK) -o t_shs3 t_shs3.o shs.o $(SUPPORT_LIB) + +check-unix: t_shs t_shs3 + $(RUN_TEST) $(C)t_shs -x + $(RUN_TEST) $(C)t_shs3 + +check-windows: $(OUTPRE)t_shs.exe $(OUTPRE)t_shs3.exe + $(OUTPRE)$(C)t_shs.exe -x + $(OUTPRE)$(C)t_shs3.exe + +clean: + $(RM) t_shs$(EXEEXT) t_shs.$(OBJEXT) t_shs3$(EXEEXT) t_shs3.$(OBJEXT) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/src/lib/crypto/builtin/sha1/deps b/src/lib/crypto/builtin/sha1/deps new file mode 100644 index 000000000000..354116cdd43c --- /dev/null +++ b/src/lib/crypto/builtin/sha1/deps @@ -0,0 +1,13 @@ +# +# Generated makefile dependencies follow. +# +shs.so shs.po $(OUTPRE)shs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h shs.c shs.h diff --git a/src/lib/crypto/builtin/sha1/shs.c b/src/lib/crypto/builtin/sha1/shs.c new file mode 100644 index 000000000000..f28a4fcbaf88 --- /dev/null +++ b/src/lib/crypto/builtin/sha1/shs.c @@ -0,0 +1,382 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include "shs.h" +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#include <string.h> + +/* The SHS f()-functions. The f1 and f3 functions can be optimized to + save one boolean operation each - thanks to Rich Schroeppel, + rcs@cs.arizona.edu for discovering this */ + +#define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */ +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ +#define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ + +/* The SHS Mysterious Constants */ + +#define K1 0x5A827999L /* Rounds 0-19 */ +#define K2 0x6ED9EBA1L /* Rounds 20-39 */ +#define K3 0x8F1BBCDCL /* Rounds 40-59 */ +#define K4 0xCA62C1D6L /* Rounds 60-79 */ + +/* SHS initial values */ + +#define h0init 0x67452301L +#define h1init 0xEFCDAB89L +#define h2init 0x98BADCFEL +#define h3init 0x10325476L +#define h4init 0xC3D2E1F0L + +/* Note that it may be necessary to add parentheses to these macros if they + are to be called with expressions as arguments */ + +/* 32-bit rotate left - kludged with shifts */ + +#define ROTL(n,X) ((((X) << (n)) & 0xffffffff) | ((X) >> (32 - n))) + +/* The initial expanding function. The hash function is defined over an + 80-word expanded input array W, where the first 16 are copies of the input + data, and the remaining 64 are defined by + + W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ] + + This implementation generates these values on the fly in a circular + buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this + optimization. + + The updated SHS changes the expanding function by adding a rotate of 1 + bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor + for this information */ + +#ifdef NEW_SHS +#define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ + W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ))) +#else +#define expand(W,i) ( W[ i & 15 ] ^= W[ (i - 14) & 15 ] ^ \ + W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) +#endif /* NEW_SHS */ + +/* The prototype SHS sub-round. The fundamental sub-round is: + + a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data; + b' = a; + c' = ROTL( 30, b ); + d' = c; + e' = d; + + but this is implemented by unrolling the loop 5 times and renaming the + variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration. + This code is then replicated 20 times for each of the 4 functions, using + the next 20 values from the W[] array each time */ + +#define subRound(a, b, c, d, e, f, k, data) \ + ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, \ + e &= 0xffffffff, b = ROTL( 30, b ) ) + +/* Initialize the SHS values */ + +void shsInit(SHS_INFO *shsInfo) +{ + /* Set the h-vars to their initial values */ + shsInfo->digest[ 0 ] = h0init; + shsInfo->digest[ 1 ] = h1init; + shsInfo->digest[ 2 ] = h2init; + shsInfo->digest[ 3 ] = h3init; + shsInfo->digest[ 4 ] = h4init; + + /* Initialise bit count */ + shsInfo->countLo = shsInfo->countHi = 0; +} + +/* Perform the SHS transformation. Note that this code, like MD5, seems to + break some optimizing compilers due to the complexity of the expressions + and the size of the basic block. It may be necessary to split it into + sections, e.g. based on the four subrounds + + Note that this corrupts the shsInfo->data area */ + +static void SHSTransform (SHS_LONG *digest, const SHS_LONG *data); + +static +void SHSTransform(SHS_LONG *digest, const SHS_LONG *data) +{ + SHS_LONG A, B, C, D, E; /* Local vars */ + SHS_LONG eData[ 16 ]; /* Expanded data */ + + /* Set up first buffer and local data buffer */ + A = digest[ 0 ]; + B = digest[ 1 ]; + C = digest[ 2 ]; + D = digest[ 3 ]; + E = digest[ 4 ]; + memcpy(eData, data, sizeof (eData)); + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) + + { + int i; + SHS_LONG temp; + for (i = 0; i < 20; i++) { + SHS_LONG x = (i < 16) ? eData[i] : expand(eData, i); + subRound(A, B, C, D, E, f1, K1, x); + temp = E, E = D, D = C, C = B, B = A, A = temp; + } + for (i = 20; i < 40; i++) { + subRound(A, B, C, D, E, f2, K2, expand(eData, i)); + temp = E, E = D, D = C, C = B, B = A, A = temp; + } + for (i = 40; i < 60; i++) { + subRound(A, B, C, D, E, f3, K3, expand(eData, i)); + temp = E, E = D, D = C, C = B, B = A, A = temp; + } + for (i = 60; i < 80; i++) { + subRound(A, B, C, D, E, f4, K4, expand(eData, i)); + temp = E, E = D, D = C, C = B, B = A, A = temp; + } + } + +#else + + /* Heavy mangling, in 4 sub-rounds of 20 interations each. */ + subRound( A, B, C, D, E, f1, K1, eData[ 0 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 1 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 2 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 3 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 4 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 5 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 6 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 7 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 8 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 9 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 10 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 11 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 12 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 13 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 14 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 15 ] ); + subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) ); + subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) ); + subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) ); + subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) ); + + subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) ); + + subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) ); + + subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) ); + +#endif + + /* Build message digest */ + digest[ 0 ] += A; + digest[ 0 ] &= 0xffffffff; + digest[ 1 ] += B; + digest[ 1 ] &= 0xffffffff; + digest[ 2 ] += C; + digest[ 2 ] &= 0xffffffff; + digest[ 3 ] += D; + digest[ 3 ] &= 0xffffffff; + digest[ 4 ] += E; + digest[ 4 ] &= 0xffffffff; +} + +/* Update SHS for a block of data */ + +void shsUpdate(SHS_INFO *shsInfo, const SHS_BYTE *buffer, unsigned int count) +{ + SHS_LONG tmp; + unsigned int dataCount; + int canfill; + SHS_LONG *lp; + + /* Update bitcount */ + tmp = shsInfo->countLo; + shsInfo->countLo = tmp + (((SHS_LONG) count) << 3 ); + if ((shsInfo->countLo &= 0xffffffff) < tmp) + shsInfo->countHi++; /* Carry from low to high */ + shsInfo->countHi += count >> 29; + + /* Get count of bytes already in data */ + dataCount = (tmp >> 3) & 0x3F; + + /* Handle any leading odd-sized chunks */ + if (dataCount) { + lp = shsInfo->data + dataCount / 4; + dataCount = SHS_DATASIZE - dataCount; + canfill = (count >= dataCount); + + if (dataCount % 4) { + /* Fill out a full 32 bit word first if needed -- this + is not very efficient (computed shift amount), + but it shouldn't happen often. */ + while (dataCount % 4 && count > 0) { + *lp |= (SHS_LONG) *buffer++ << ((--dataCount % 4) * 8); + count--; + } + lp++; + } + while (lp < shsInfo->data + 16) { + if (count < 4) { + *lp = 0; + switch (count % 4) { + case 3: + *lp |= (SHS_LONG) buffer[2] << 8; + case 2: + *lp |= (SHS_LONG) buffer[1] << 16; + case 1: + *lp |= (SHS_LONG) buffer[0] << 24; + } + count = 0; + break; /* out of while loop */ + } + *lp++ = load_32_be(buffer); + buffer += 4; + count -= 4; + } + if (canfill) { + SHSTransform(shsInfo->digest, shsInfo->data); + } + } + + /* Process data in SHS_DATASIZE chunks */ + while (count >= SHS_DATASIZE) { + lp = shsInfo->data; + while (lp < shsInfo->data + 16) { + *lp++ = load_32_be(buffer); + buffer += 4; + } + SHSTransform(shsInfo->digest, shsInfo->data); + count -= SHS_DATASIZE; + } + + if (count > 0) { + lp = shsInfo->data; + while (count > 4) { + *lp++ = load_32_be(buffer); + buffer += 4; + count -= 4; + } + *lp = 0; + switch (count % 4) { + case 0: + *lp |= ((SHS_LONG) buffer[3]); + case 3: + *lp |= ((SHS_LONG) buffer[2]) << 8; + case 2: + *lp |= ((SHS_LONG) buffer[1]) << 16; + case 1: + *lp |= ((SHS_LONG) buffer[0]) << 24; + } + } +} + +/* Final wrapup - pad to SHS_DATASIZE-byte boundary with the bit pattern + 1 0* (64-bit count of bits processed, MSB-first) */ + +void shsFinal(SHS_INFO *shsInfo) +{ + int count; + SHS_LONG *lp; + + /* Compute number of bytes mod 64 */ + count = (int) shsInfo->countLo; + count = (count >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + lp = shsInfo->data + count / 4; + switch (count % 4) { + case 3: + *lp++ |= (SHS_LONG) 0x80; + break; + case 2: + *lp++ |= (SHS_LONG) 0x80 << 8; + break; + case 1: + *lp++ |= (SHS_LONG) 0x80 << 16; + break; + case 0: + *lp++ = (SHS_LONG) 0x80 << 24; + } + + /* at this point, lp can point *past* shsInfo->data. If it points + there, just Transform and reset. If it points to the last + element, set that to zero. This pads out to 64 bytes if not + enough room for length words */ + + if (lp == shsInfo->data + 15) + *lp++ = 0; + + if (lp == shsInfo->data + 16) { + SHSTransform(shsInfo->digest, shsInfo->data); + lp = shsInfo->data; + } + + /* Pad out to 56 bytes */ + while (lp < shsInfo->data + 14) + *lp++ = 0; + + /* Append length in bits and transform */ + *lp++ = shsInfo->countHi; + *lp++ = shsInfo->countLo; + SHSTransform(shsInfo->digest, shsInfo->data); +} diff --git a/src/lib/crypto/builtin/sha1/shs.h b/src/lib/crypto/builtin/sha1/shs.h new file mode 100644 index 000000000000..e1872f2e5105 --- /dev/null +++ b/src/lib/crypto/builtin/sha1/shs.h @@ -0,0 +1,46 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#ifndef _SHS_DEFINED + +#include "k5-int.h" + +#define _SHS_DEFINED + +/* Some useful types */ + +typedef krb5_octet SHS_BYTE; +typedef krb5_ui_4 SHS_LONG; + +/* Define the following to use the updated SHS implementation */ +#define NEW_SHS /**/ + +/* The SHS block size and message digest sizes, in bytes */ + +#define SHS_DATASIZE 64 +#define SHS_DIGESTSIZE 20 + +/* The structure for storing SHS info */ + +typedef struct { + SHS_LONG digest[ 5 ]; /* Message digest */ + SHS_LONG countLo, countHi; /* 64-bit bit count */ + SHS_LONG data[ 16 ]; /* SHS data buffer */ +} SHS_INFO; + +/* Message digest functions (shs.c) */ +void shsInit(SHS_INFO *shsInfo); +void shsUpdate(SHS_INFO *shsInfo, const SHS_BYTE *buffer, unsigned int count); +void shsFinal(SHS_INFO *shsInfo); + + +/* Keyed Message digest functions (hmac_sha.c) */ +krb5_error_code hmac_sha(krb5_octet *text, + int text_len, + krb5_octet *key, + int key_len, + krb5_octet *digest); + + +#define NIST_SHA_CKSUM_LENGTH SHS_DIGESTSIZE +#define HMAC_SHA_CKSUM_LENGTH SHS_DIGESTSIZE + +#endif /* _SHS_DEFINED */ diff --git a/src/lib/crypto/builtin/sha1/t_shs.c b/src/lib/crypto/builtin/sha1/t_shs.c new file mode 100644 index 000000000000..08157b662230 --- /dev/null +++ b/src/lib/crypto/builtin/sha1/t_shs.c @@ -0,0 +1,136 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/**************************************************************************** + * * + * SHS Test Code * + * * + ****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include "shs.h" + +/* Test the SHS implementation */ + +#ifdef NEW_SHS + +static SHS_LONG shsTestResults[][ 5 ] = { + { 0xA9993E36L, 0x4706816AL, 0xBA3E2571L, 0x7850C26CL, 0x9CD0D89DL, }, + { 0x84983E44L, 0x1C3BD26EL, 0xBAAE4AA1L, 0xF95129E5L, 0xE54670F1L, }, + { 0x34AA973CL, 0xD4C4DAA4L, 0xF61EEB2BL, 0xDBAD2731L, 0x6534016FL, } +}; + +#else + +static SHS_LONG shsTestResults[][ 5 ] = { + { 0x0164B8A9L, 0x14CD2A5EL, 0x74C4F7FFL, 0x082C4D97L, 0xF1EDF880L }, + { 0xD2516EE1L, 0xACFA5BAFL, 0x33DFC1C4L, 0x71E43844L, 0x9EF134C8L }, + { 0x3232AFFAL, 0x48628A26L, 0x653B5AAAL, 0x44541FD9L, 0x0D690603L } +}; +#endif /* NEW_SHS */ + +static int compareSHSresults(shsInfo, shsTestLevel) + SHS_INFO *shsInfo; + int shsTestLevel; +{ + int i, fail = 0; + + /* Compare the returned digest and required values */ + for( i = 0; i < 5; i++ ) + if( shsInfo->digest[ i ] != shsTestResults[ shsTestLevel ][ i ] ) + fail = 1; + if (fail) { + printf("\nExpected: "); + for (i = 0; i < 5; i++) { + printf("%8.8lx ", (unsigned long) shsTestResults[shsTestLevel][i]); + } + printf("\nGot: "); + for (i = 0; i < 5; i++) { + printf("%8.8lx ", (unsigned long) shsInfo->digest[i]); + } + printf("\n"); + return( -1 ); + } + return( 0 ); +} + +int +main() +{ + SHS_INFO shsInfo; + unsigned int i; +#if 0 + time_t secondCount; + SHS_BYTE data[ 200 ]; +#endif + + /* Make sure we've got the endianness set right. If the machine is + big-endian (up to 64 bits) the following value will be signed, + otherwise it will be unsigned. Unfortunately we can't test for odd + things like middle-endianness without knowing the size of the data + types */ + + /* Test SHS against values given in SHS standards document */ + printf( "Running SHS test 1 ... " ); + shsInit( &shsInfo ); + shsUpdate( &shsInfo, ( SHS_BYTE * ) "abc", 3 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 0 ) == -1 ) + { + putchar( '\n' ); + puts( "SHS test 1 failed" ); + exit( -1 ); + } +#ifdef NEW_SHS + puts( "passed, result= A9993E364706816ABA3E25717850C26C9CD0D89D" ); +#else + puts( "passed, result= 0164B8A914CD2A5E74C4F7FF082C4D97F1EDF880" ); +#endif /* NEW_SHS */ + + printf( "Running SHS test 2 ... " ); + shsInit( &shsInfo ); + shsUpdate( &shsInfo, ( SHS_BYTE * ) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 1 ) == -1 ) + { + putchar( '\n' ); + puts( "SHS test 2 failed" ); + exit( -1 ); + } +#ifdef NEW_SHS + puts( "passed, result= 84983E441C3BD26EBAAE4AA1F95129E5E54670F1" ); +#else + puts( "passed, result= D2516EE1ACFA5BAF33DFC1C471E438449EF134C8" ); +#endif /* NEW_SHS */ + + printf( "Running SHS test 3 ... " ); + shsInit( &shsInfo ); + for( i = 0; i < 15625; i++ ) + shsUpdate( &shsInfo, ( SHS_BYTE * ) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 2 ) == -1 ) + { + putchar( '\n' ); + puts( "SHS test 3 failed" ); + exit( -1 ); + } +#ifdef NEW_SHS + puts( "passed, result= 34AA973CD4C4DAA4F61EEB2BDBAD27316534016F" ); +#else + puts( "passed, result= 3232AFFA48628A26653B5AAA44541FD90D690603" ); +#endif /* NEW_SHS */ + +#if 0 + printf( "\nTesting speed for 100MB data... " ); + shsInit( &shsInfo ); + secondCount = time( NULL ); + for( i = 0; i < 500000U; i++ ) + shsUpdate( &shsInfo, data, 200 ); + secondCount = time( NULL ) - secondCount; + printf( "done. Time = %ld seconds, %ld kbytes/second.\n", \ + secondCount, 100500L / secondCount ); +#endif + + puts( "\nAll SHS tests passed" ); + exit( 0 ); +} diff --git a/src/lib/crypto/builtin/sha1/t_shs3.c b/src/lib/crypto/builtin/sha1/t_shs3.c new file mode 100644 index 000000000000..f7932ef0fd44 --- /dev/null +++ b/src/lib/crypto/builtin/sha1/t_shs3.c @@ -0,0 +1,594 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* test shs code */ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include "shs.h" + +static void process(void); +static void test1(void); +static void test2(void); +static void test3(void); +static void test4(void); +static void test5(void); +static void test6(void); +static void test7(void); + +/* When run on a little-endian CPU we need to perform byte reversal on an + array of longwords. It is possible to make the code endianness- + independant by fiddling around with data at the byte level, but this + makes for very slow code, so we rely on the user to sort out endianness + at compile time */ + +static void longReverse( SHS_LONG *buffer, int byteCount ) +{ + SHS_LONG value; + static int init = 0; + char *cp; + + switch (init) { + case 0: + init=1; + cp = (char *) &init; + if (*cp == 1) { + init=2; + break; + } + init=1; + /* fall through - MSB */ + case 1: + return; + } + + byteCount /= sizeof( SHS_LONG ); + while( byteCount-- ) { + value = *buffer; + value = ( ( value & 0xFF00FF00L ) >> 8 ) | + ( ( value & 0x00FF00FFL ) << 8 ); + *buffer++ = ( value << 16 ) | ( value >> 16 ); + } +} + +int rc; +int mode; +int Dflag; + +int +main(argc,argv) + int argc; + char **argv; +{ + char *argp; + + while (--argc > 0) if (*(argp = *++argv)=='-') + while (*++argp) switch(*argp) + { + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + if (mode) goto Usage; + mode = *argp; + break; + case 'D': + if (argc <= 1) goto Usage; + --argc; + Dflag = atoi(*++argv); + break; + case '-': + break; + default: + fprintf (stderr,"Bad switch char <%c>\n", *argp); + Usage: + fprintf(stderr, "Usage: t_shs [-1234567] [-D #]\n"); + exit(1); + } + else goto Usage; + + process(); + exit(rc); +} + +static void process(void) +{ + switch(mode) + { + case '1': + test1(); + break; + case '2': + test2(); + break; + case '3': + test3(); + break; + case '4': + test4(); + break; + case '5': + test5(); + break; + case '6': + test6(); + break; + case '7': + test7(); + break; + default: + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + test7(); + } +} + +#ifndef shsDigest +static unsigned char * +shsDigest(si) + SHS_INFO *si; +{ + longReverse(si->digest, SHS_DIGESTSIZE); + return (unsigned char*) si->digest; +} +#endif + +unsigned char results1[SHS_DIGESTSIZE] = { + 0xa9,0x99,0x3e,0x36,0x47,0x06,0x81,0x6a,0xba,0x3e, + 0x25,0x71,0x78,0x50,0xc2,0x6c,0x9c,0xd0,0xd8,0x9d}; + +static void test1(void) +{ + SHS_INFO si[1]; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + int i; + + printf("Running SHS test 1 ...\n"); + shsInit(si); + shsUpdate(si, (SHS_BYTE *) "abc", 3); + shsFinal(si); + memcpy(digest, shsDigest(si), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results1, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 1 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results1[i]); + } + printf("\n"); +} + +unsigned char results2[SHS_DIGESTSIZE] = { + 0x84,0x98,0x3e,0x44,0x1c,0x3b,0xd2,0x6e,0xba,0xae, + 0x4a,0xa1,0xf9,0x51,0x29,0xe5,0xe5,0x46,0x70,0xf1}; + +static void test2(void) +{ + SHS_INFO si[1]; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + int i; + + printf("Running SHS test 2 ...\n"); + shsInit(si); + shsUpdate(si, + (SHS_BYTE *) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + 56); + shsFinal(si); + memcpy(digest, shsDigest(si), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results2, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 2 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results2[i]); + } + printf("\n"); +} + +unsigned char results3[SHS_DIGESTSIZE] = { + 0x34,0xaa,0x97,0x3c,0xd4,0xc4,0xda,0xa4,0xf6,0x1e, + 0xeb,0x2b,0xdb,0xad,0x27,0x31,0x65,0x34,0x01,0x6f}; + +static void test3(void) +{ + SHS_INFO si[1]; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + int i; + + printf("Running SHS test 3 ...\n"); + shsInit(si); + for (i = 0; i < 15625; ++i) + shsUpdate(si, + (SHS_BYTE *) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + 64); + shsFinal(si); + memcpy(digest, shsDigest(si), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results3, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 3 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results3[i]); + } + printf("\n"); +} + +unsigned char randdata[] = { + 0xfe,0x28,0x79,0x25,0xf5,0x03,0xf9,0x1c,0xcd,0x70,0x7b,0xb0,0x42,0x02,0xb8,0x2f, + 0xf3,0x63,0xa2,0x79,0x8e,0x9b,0x33,0xd7,0x2b,0xc4,0xb4,0xd2,0xcb,0x61,0xec,0xbb, + 0x94,0xe1,0x8f,0x53,0x80,0x55,0xd9,0x90,0xb2,0x03,0x58,0xfa,0xa6,0xe5,0x18,0x57, + 0x68,0x04,0x24,0x98,0x41,0x7e,0x84,0xeb,0xc1,0x39,0xbc,0x1d,0xf7,0x4e,0x92,0x72, + 0x1a,0x5b,0xb6,0x99,0x43,0xa5,0x0a,0x45,0x73,0x55,0xfd,0x57,0x83,0x45,0x36,0x5c, + 0xfd,0x39,0x08,0x6e,0xe2,0x01,0x9a,0x8c,0x4e,0x39,0xd2,0x0d,0x5f,0x0e,0x35,0x15, + 0xb9,0xac,0x5f,0xa1,0x8a,0xe6,0xdd,0x6e,0x68,0x9d,0xf6,0x29,0x95,0xf6,0x7d,0x7b, + 0xd9,0x5e,0xf4,0x67,0x25,0xbd,0xee,0xed,0x53,0x60,0xb0,0x47,0xdf,0xef,0xf4,0x41, + 0xbd,0x45,0xcf,0x5c,0x93,0x41,0x87,0x97,0x82,0x39,0x20,0x66,0xb4,0xda,0xcb,0x66, + 0x93,0x02,0x2e,0x7f,0x94,0x4c,0xc7,0x3b,0x2c,0xcf,0xf6,0x99,0x6f,0x13,0xf1,0xc5, + 0x28,0x2b,0xa6,0x6c,0x39,0x26,0x7f,0x76,0x24,0x4a,0x6e,0x01,0x40,0x63,0xf8,0x00, + 0x06,0x23,0x5a,0xaa,0xa6,0x2f,0xd1,0x37,0xc7,0xcc,0x76,0xe9,0x54,0x1e,0x57,0x73, + 0xf5,0x33,0xaa,0x96,0xbe,0x35,0xcd,0x1d,0xd5,0x7d,0xac,0x50,0xd5,0xf8,0x47,0x2d, + 0xd6,0x93,0x5f,0x6e,0x38,0xd3,0xac,0xd0,0x7e,0xad,0x9e,0xf8,0x87,0x95,0x63,0x15, + 0x65,0xa3,0xd4,0xb3,0x9a,0x6c,0xac,0xcd,0x2a,0x54,0x83,0x13,0xc4,0xb4,0x94,0xfa, + 0x76,0x87,0xc5,0x8b,0x4a,0x10,0x92,0x05,0xd1,0x0e,0x97,0xfd,0xc8,0xfb,0xc5,0xdc, + 0x21,0x4c,0xc8,0x77,0x5c,0xed,0x32,0x22,0x77,0xc1,0x38,0x30,0xd7,0x8e,0x2a,0x70, + 0x72,0x67,0x13,0xe4,0xb7,0x18,0xd4,0x76,0xdd,0x32,0x12,0xf4,0x5d,0xc9,0xec,0xc1, + 0x2c,0x8a,0xfe,0x08,0x6c,0xea,0xf6,0xab,0x5a,0x0e,0x8e,0x81,0x1d,0xc8,0x5a,0x4b, + 0xed,0xb9,0x7f,0x4b,0x67,0xe3,0x65,0x46,0xc9,0xf2,0xab,0x37,0x0a,0x98,0x67,0x5b, + 0xb1,0x3b,0x02,0x91,0x38,0x71,0xea,0x62,0x88,0xae,0xb6,0xdb,0xfc,0x55,0x79,0x33, + 0x69,0x95,0x51,0xb6,0xe1,0x3b,0xab,0x22,0x68,0x54,0xf9,0x89,0x9c,0x94,0xe0,0xe3, + 0xd3,0x48,0x5c,0xe9,0x78,0x5b,0xb3,0x4b,0xba,0xd8,0x48,0xd8,0xaf,0x91,0x4e,0x23, + 0x38,0x23,0x23,0x6c,0xdf,0x2e,0xf0,0xff,0xac,0x1d,0x2d,0x27,0x10,0x45,0xa3,0x2d, + 0x8b,0x00,0xcd,0xe2,0xfc,0xb7,0xdb,0x52,0x13,0xb7,0x66,0x79,0xd9,0xd8,0x29,0x0e, + 0x32,0xbd,0x52,0x6b,0x75,0x71,0x08,0x83,0x1b,0x67,0x28,0x93,0x97,0x97,0x32,0xff, + 0x8b,0xd3,0x98,0xa3,0xce,0x2b,0x88,0x37,0x1c,0xcc,0xa0,0xd1,0x19,0x9b,0xe6,0x11, + 0xfc,0xc0,0x3c,0x4e,0xe1,0x35,0x49,0x29,0x19,0xcf,0x1d,0xe1,0x60,0x74,0xc0,0xe9, + 0xf7,0xb4,0x99,0xa0,0x23,0x50,0x51,0x78,0xcf,0xc0,0xe5,0xc2,0x1c,0x16,0xd2,0x24, + 0x5a,0x63,0x54,0x83,0xaa,0x74,0x3d,0x41,0x0d,0x52,0xee,0xfe,0x0f,0x4d,0x13,0xe1, + 0x27,0x00,0xc4,0xf3,0x2b,0x55,0xe0,0x9c,0x81,0xe0,0xfc,0xc2,0x13,0xd4,0x39,0x09 +}; + +unsigned char results4[SHS_DIGESTSIZE] = { + 0x13,0x62,0xfc,0x87,0x68,0x33,0xd5,0x1d,0x2f,0x0c, + 0x73,0xe3,0xfb,0x87,0x6a,0x6b,0xc3,0x25,0x54,0xfc}; + +static void test4(void) +{ + SHS_INFO si[1]; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + int i; + + printf("Running SHS test 4 ...\n"); + shsInit(si); + shsUpdate(si, randdata, 19); + shsFinal(si); + memcpy(digest, shsDigest(si), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results4, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 4 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results4[i]); + } + printf("\n"); +} + +unsigned char results5[SHS_DIGESTSIZE] = { + 0x19,0x4d,0xf6,0xeb,0x8e,0x02,0x6d,0x37,0x58,0x64, + 0xe5,0x95,0x19,0x2a,0xdd,0x1c,0xc4,0x3c,0x24,0x86}; + +static void test5(void) +{ + SHS_INFO si[1]; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + int i; + + printf("Running SHS test 5 ...\n"); + shsInit(si); + shsUpdate(si, randdata, 19); + shsUpdate(si, randdata+32, 15); + shsFinal(si); + memcpy(digest, shsDigest(si), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results5, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 5 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results5[i]); + } + printf("\n"); +} + +unsigned char results6[SHS_DIGESTSIZE] = { + 0x4e,0x16,0x57,0x9d,0x4b,0x48,0xa9,0x1c,0x88,0x72, + 0x83,0xdb,0x88,0xd1,0xea,0x3a,0x45,0xdf,0xa1,0x10}; + +static void test6(void) +{ + struct { + unsigned long pad1; + SHS_INFO si1; + unsigned long pad2; + SHS_INFO si2; + unsigned long pad3; + } sdata; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + unsigned int i, j; + + printf("Running SHS test 6 ...\n"); + sdata.pad1 = 0x12345678; + sdata.pad2 = 0x87654321; + sdata.pad3 = 0x78563412; + shsInit((&sdata.si2)); + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #20 %#lx\n", + sdata.pad2); + sdata.pad2 = 0x87654321; + } + if (sdata.pad3 != 0x78563412) { + printf ("Overrun #21 %#lx\n", + sdata.pad3); + sdata.pad3 = 0x78563412; + } + for (i = 0; i < 400; ++i) + { + shsInit(&sdata.si1); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #22 %#lx at %d\n", + sdata.pad1, i); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #23 %#lx at %d\n", + sdata.pad2, i); + sdata.pad2 = 0x87654321; + } + shsUpdate(&sdata.si1, (randdata+sizeof(randdata))-i, i); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #24 %#lx at %d\n", + sdata.pad1, i); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #25 %#lx at %d\n", + sdata.pad2, i); + sdata.pad2 = 0x87654321; + } + shsFinal(&sdata.si1); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #26 %#lx at %d\n", + sdata.pad1, i); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #27 %#lx at %d\n", + sdata.pad2, i); + sdata.pad2 = 0x87654321; + } + memcpy(digest, shsDigest(&sdata.si1), SHS_DIGESTSIZE); + if (Dflag & 1) + { + printf ("%d: ", i); + for (j = 0; j < SHS_DIGESTSIZE; ++j) + printf("%02x",digest[j]); + printf("\n"); + } + shsUpdate((&sdata.si2), digest, SHS_DIGESTSIZE); + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #28 %#lx at %d\n", + sdata.pad2, i); + sdata.pad2 = 0x87654321; + } + if (sdata.pad3 != 0x78563412) { + printf ("Overrun #29 %#lx at %d\n", + sdata.pad3, i); + sdata.pad3 = 0x78563412; + } + if (Dflag & 2) + printf ("%d: %08lx%08lx%08lx%08lx%08lx\n", + i, + (unsigned long) sdata.si2.digest[0], + (unsigned long) sdata.si2.digest[1], + (unsigned long) sdata.si2.digest[2], + (unsigned long) sdata.si2.digest[3], + (unsigned long) sdata.si2.digest[4]); + } + shsFinal((&sdata.si2)); + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #30 %#lx\n", + sdata.pad2); + sdata.pad2 = 0x87654321; + } + if (sdata.pad3 != 0x78563412) { + printf ("Overrun #31 %#lx\n", + sdata.pad3); + sdata.pad3 = 0x78563412; + } + memcpy(digest, shsDigest((&sdata.si2)), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results6, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 6 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results6[i]); + } + printf("\n"); +} + +unsigned char results7[SHS_DIGESTSIZE] = { + 0x89,0x41,0x65,0xce,0x76,0xc1,0xd1,0xd1,0xc3,0x6f, + 0xab,0x92,0x79,0x30,0x01,0x71,0x63,0x1f,0x74,0xfe}; + +unsigned int jfsize[] = {0,1,31,32, + 33,55,56,63, + 64,65,71,72, + 73,95,96,97, + 119,120,123,127}; +unsigned int kfsize[] = {0,1,31,32,33,55,56,63}; + +static void test7(void) +{ + struct { + unsigned long pad1; + SHS_INFO si1; + unsigned long pad2; + SHS_INFO si2; + unsigned long pad3; + } sdata; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + unsigned int i, j, k, l; + + printf("Running SHS test 7 ...\n"); + sdata.pad1 = 0x12345678; + sdata.pad2 = 0x87654321; + sdata.pad3 = 0x78563412; + shsInit((&sdata.si2)); + for (i = 1; i <= 128; ++i) + for (j = 0; j < 20; ++j) + for (k = 0; k < 8; ++k) + { + shsInit(&sdata.si1); + shsUpdate(&sdata.si1, (randdata+80+j), i); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #1 %#lx at %d,%d,%d\n", + sdata.pad1, i,j,k); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #2 %#lx at %d,%d,%d\n", + sdata.pad2, i,j,k); + sdata.pad2 = 0x87654321; + } + shsUpdate(&sdata.si1, randdata+i, jfsize[j]); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #3 %#lx at %d,%d,%d\n", + sdata.pad1, i,j,k); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #4 %#lx at %d,%d,%d\n", + sdata.pad2, i,j,k); + sdata.pad2 = 0x87654321; + } + if (k) shsUpdate(&sdata.si1, randdata+(i^j), kfsize[k]); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #5 %#lx at %d,%d,%d\n", + sdata.pad1, i,j,k); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #6 %#lx at %d,%d,%d\n", + sdata.pad2, i,j,k); + sdata.pad2 = 0x87654321; + } + shsFinal(&sdata.si1); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #7 %#lx at %d,%d,%d\n", + sdata.pad1, i,j,k); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #8 %#lx at %d,%d,%d\n", + sdata.pad2, i,j,k); + sdata.pad2 = 0x87654321; + } + memcpy(digest, shsDigest(&sdata.si1), SHS_DIGESTSIZE); + if (Dflag & 1) + { + printf ("%d,%d,%d: ", i, j, k); + for (l = 0; l < SHS_DIGESTSIZE; ++l) + printf("%02x",digest[l]); + printf("\n"); + } + shsUpdate((&sdata.si2), digest, SHS_DIGESTSIZE); + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #9 %#lx at %d,%d,%d\n", + sdata.pad2, i,j,k); + sdata.pad2 = 0x87654321; + } + if (sdata.pad3 != 0x78563412) { + printf ("Overrun #10 %#lx at %d,%d,%d\n", + sdata.pad3, i,j,k); + sdata.pad3 = 0x78563412; + } + if (Dflag & 2) + printf ("%d,%d,%d: %08lx%08lx%08lx%08lx%08lx\n", |