diff options
Diffstat (limited to 'src/lib/crypto/builtin')
63 files changed, 11030 insertions, 0 deletions
diff --git a/src/lib/crypto/builtin/Makefile.in b/src/lib/crypto/builtin/Makefile.in new file mode 100644 index 0000000..03ca5e9 --- /dev/null +++ b/src/lib/crypto/builtin/Makefile.in @@ -0,0 +1,123 @@ +thisconfigdir=../../.. +myfulldir=lib/crypto/builtin +mydir=lib/crypto/builtin +BUILDTOP=$(REL)..$(S)..$(S).. +SUBDIRS=../@CRYPTO_IMPL@/des ../@CRYPTO_IMPL@/arcfour ../@CRYPTO_IMPL@/aes \ + ../@CRYPTO_IMPL@/md4 ../@CRYPTO_IMPL@/md5 ../@CRYPTO_IMPL@/sha1 +LOCALINCLUDES = -I$(srcdir)/../krb -I$(srcdir)/../krb/hash_provider \ + -I$(srcdir)/../@CRYPTO_IMPL@/des \ + -I$(srcdir)/../@CRYPTO_IMPL@/aes \ + -I$(srcdir)/../@CRYPTO_IMPL@/arcfour \ + -I$(srcdir)/../@CRYPTO_IMPL@/sha1 \ + -I$(srcdir)/../@CRYPTO_IMPL@/md4 \ + -I$(srcdir)/../@CRYPTO_IMPL@/md5 +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) +DEFS= + + +##DOSBUILDTOP = ..\..\.. +##DOSLIBNAME=$(OUTPRE)crypto.lib +##DOSOBJFILE=$(OUTPRE)crypto.lst +##DOSOBJFILELIST=@$(OUTPRE)crypto.lst @$(OUTPRE)des.lst @$(OUTPRE)md4.lst @$(OUTPRE)md5.lst @$(OUTPRE)sha1.lst @$(OUTPRE)arcfour.lst @$(OUTPRE)crc32.lst @$(OUTPRE)dk.lst @$(OUTPRE)old.lst @$(OUTPRE)raw.lst @$(OUTPRE)enc_prov.lst @$(OUTPRE)hash_pro.lst @$(OUTPRE)kh_pro.lst @$(OUTPRE)yarrow.lst @$(OUTPRE)aes.lst +##DOSOBJFILEDEP =$(OUTPRE)crypto.lst $(OUTPRE)des.lst $(OUTPRE)md4.lst $(OUTPRE)md5.lst $(OUTPRE)sha1.lst $(OUTPRE)arcfour.lst $(OUTPRE)crc32.lst $(OUTPRE)dk.lst $(OUTPRE)old.lst $(OUTPRE)raw.lst $(OUTPRE)enc_prov.lst $(OUTPRE)hash_pro.lst $(OUTPRE)kh_pro.lst $(OUTPRE)aes.lst + +STLIBOBJS=\ + hmac.o \ + pbkdf2.o + +OBJS=\ + $(OUTPRE)../@CRYPTO_IMPL@/hmac.$(OBJEXT) \ + $(OUTPRE)../@CRYPTO_IMPL@/pbkdf2.$(OBJEXT) + +SRCS=\ + $(srcdir)/../@CRYPTO_IMPL@/hmac.c \ + $(srcdir)/../@CRYPTO_IMPL@/pbkdf2.c + +STOBJLISTS= ../@CRYPTO_IMPL@/des/OBJS.ST ../@CRYPTO_IMPL@/md4/OBJS.ST \ + ../@CRYPTO_IMPL@/md5/OBJS.ST ../@CRYPTO_IMPL@/sha1/OBJS.ST \ + ../@CRYPTO_IMPL@/arcfour/OBJS.ST \ + ../@CRYPTO_IMPL@/aes/OBJS.ST \ + ../@CRYPTO_IMPL@/OBJS.ST + +SUBDIROBJLISTS= ../@CRYPTO_IMPL@/des/OBJS.ST ../@CRYPTO_IMPL@/md4/OBJS.ST \ + ../@CRYPTO_IMPL@/md5/OBJS.ST ../@CRYPTO_IMPL@/sha1/OBJS.ST \ + ../@CRYPTO_IMPL@/arcfour/OBJS.ST \ + ../@CRYPTO_IMPL@/aes/OBJS.ST ../@CRYPTO_IMPL@/OBJS.ST + +##DOS##LIBOBJS = $(OBJS) + +all-unix:: all-libobjs +includes:: depend + +depend:: $(SRCS) + +clean-unix:: clean-libobjs + +all-windows:: + cd ..\des + @echo Making in crypto\des + $(MAKE) -$(MFLAGS) + cd ..\md4 + @echo Making in crypto\md4 + $(MAKE) -$(MFLAGS) + cd ..\md5 + @echo Making in crypto\md5 + $(MAKE) -$(MFLAGS) + cd ..\sha1 + @echo Making in crypto\sha1 + $(MAKE) -$(MFLAGS) + cd ..\arcfour + @echo Making in crypto\arcfour + $(MAKE) -$(MFLAGS) + cd ..\aes + @echo Making in crypto\aes + $(MAKE) -$(MFLAGS) + cd .. + +clean-windows:: + cd ..\des + @echo Making clean in crypto\des + $(MAKE) -$(MFLAGS) clean + cd ..\md4 + @echo Making clean in crypto\md4 + $(MAKE) -$(MFLAGS) clean + cd ..\md5 + @echo Making clean in crypto\md5 + $(MAKE) -$(MFLAGS) clean + cd ..\sha1 + @echo Making clean in crypto\sha1 + $(MAKE) -$(MFLAGS) clean + cd ..\arcfour + @echo Making clean in crypto\arcfour + $(MAKE) -$(MFLAGS) clean + cd ..\aes + @echo Making clean in crypto\aes + $(MAKE) -$(MFLAGS) clean + cd .. + +check-windows:: + cd ..\des + @echo Making check in crypto\des + $(MAKE) -$(MFLAGS) check + cd ..\md4 + @echo Making check in crypto\md4 + $(MAKE) -$(MFLAGS) check + cd ..\md5 + @echo Making check in crypto\md5 + $(MAKE) -$(MFLAGS) check + cd ..\sha1 + @echo Making check in crypto\sha1 + $(MAKE) -$(MFLAGS) check + cd ..\arcfour + @echo Making check in crypto\arcfour + $(MAKE) -$(MFLAGS) check + cd ..\aes + @echo Making check in crypto\aes + $(MAKE) -$(MFLAGS) check + cd .. + + +@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 0000000..ed36f7e --- /dev/null +++ b/src/lib/crypto/builtin/aes/Makefile.in @@ -0,0 +1,61 @@ +thisconfigdir=../../../.. +myfulldir=lib/crypto/builtin/aes +mydir=lib/crypto/builtin/aes +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../krb/dk +DEFS= + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR=aes +##DOS##OBJFILE=..\$(OUTPRE)aes.lst + +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) + +STLIBOBJS=\ + aescrypt.o \ + aestab.o \ + aeskey.o \ + aes_s2k.o + +OBJS=\ + $(OUTPRE)aescrypt.$(OBJEXT) \ + $(OUTPRE)aestab.$(OBJEXT) \ + $(OUTPRE)aeskey.$(OBJEXT) \ + $(OUTPRE)aes_s2k.$(OBJEXT) + +SRCS=\ + $(srcdir)/aescrypt.c \ + $(srcdir)/aestab.c \ + $(srcdir)/aeskey.c \ + $(srcdir)/aes_s2k.c + +GEN_OBJS=\ + $(OUTPRE)aescrypt.$(OBJEXT) \ + $(OUTPRE)aestab.$(OBJEXT) \ + $(OUTPRE)aeskey.$(OBJEXT) + +##DOS##LIBOBJS = $(OBJS) + +all-unix:: all-libobjs # aes-gen + +includes:: depend + +depend:: $(SRCS) + +aes-gen: aes-gen.o $(GEN_OBJS) + $(CC_LINK) -o aes-gen aes-gen.o $(GEN_OBJS) + +run-aes-gen: aes-gen + ./aes-gen > kresults.out + +check:: run-aes-gen + + +clean-unix:: clean-libobjs + +clean:: + -$(RM) aes-gen aes-gen.o kresults.out + +@libobj_frag@ + diff --git a/src/lib/crypto/builtin/aes/aes-gen.c b/src/lib/crypto/builtin/aes/aes-gen.c new file mode 100644 index 0000000..855e6a4 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aes-gen.c @@ -0,0 +1,326 @@ +/* + * To be compiled against the AES code from: + * http://fp.gladman.plus.com/cryptography_technology/rijndael/index.htm + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include "aes.h" + +#define B 16U +unsigned char key[16]; +unsigned char test_case_len[] = { B+1, 2*B-1, 2*B, 2*B+1, 3*B-1, 3*B, 4*B, }; +#define NTESTS (sizeof(test_case_len)) +struct { + unsigned char ivec[16]; + unsigned char input[4*16]; + unsigned char output[4*16]; +} test_case[NTESTS]; +aes_ctx ctx, dctx; + +static void init () +{ + int i, j, r; + + srand(42); + for (i = 0; i < 16; i++) + key[i] = 0xff & rand(); + memset(test_case, 0, sizeof(test_case)); + for (i = 0; i < NTESTS; i++) + for (j = 0; j < test_case_len[i]; j++) { + test_case[i].input[j] = 0xff & rand(); + } + + r = aes_enc_key (key, sizeof(key), &ctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = aes_dec_key (key, sizeof(key), &dctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); +} + +static void hexdump(const unsigned char *ptr, size_t len) +{ + int i; + for (i = 0; i < len; i++) + printf ("%s%02X", (i % 16 == 0) ? "\n " : " ", ptr[i]); +} + +static void fips_test () +{ + static const unsigned char fipskey[16] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + }; + static const unsigned char input[16] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }; + static const unsigned char expected[16] = { + 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a, + }; + unsigned char output[16]; + unsigned char tmp[16]; + aes_ctx fipsctx; + int r; + + printf ("FIPS test:\nkey:"); + hexdump (fipskey, 16); + printf ("\ninput:"); + hexdump (input, 16); + r = aes_enc_key (fipskey, sizeof(fipskey), &fipsctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = aes_enc_blk (input, output, &fipsctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + printf ("\noutput:"); + hexdump (output, 16); + printf ("\n"); + if (memcmp(expected, output, 16)) + fprintf(stderr, "wrong results!!!\n"), exit (1); + r = aes_dec_key (fipskey, sizeof(fipskey), &fipsctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = aes_dec_blk (output, tmp, &fipsctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + if (memcmp(input, tmp, 16)) + fprintf(stderr, "decryption failed!!\n"), exit(1); + printf ("ok.\n\n"); +} + +static void +xor (unsigned char *out, const unsigned char *a, const unsigned char *b) +{ + int i; + for (i = 0; i < B; i++) + out[i] = a[i] ^ b[i]; +} + +static void +ecb_enc (unsigned char *out, unsigned char *in, unsigned int len) +{ + int i, r; + for (i = 0; i < len; i += 16) { + r = aes_enc_blk (in + i, out + i, &ctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + } + if (i != len) abort (); +} + +static void +ecb_dec (unsigned char *out, unsigned char *in, unsigned int len) +{ + int i, r; + for (i = 0; i < len; i += 16) { + r = aes_dec_blk (in + i, out + i, &dctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + } + if (i != len) abort (); +} + +#define D(X) (printf("%s %d: %s=",__FUNCTION__,__LINE__, #X),hexdump(X,B),printf("\n")) + +#undef D +#define D(X) + +static void +cbc_enc (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + int i, r; + unsigned char tmp[B]; + D(iv); + memcpy (tmp, iv, B); + for (i = 0; i < len; i += B) { + D(in+i); + xor (tmp, tmp, in + i); + D(tmp); + r = aes_enc_blk (tmp, out + i, &ctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + memcpy (tmp, out + i, B); + D(out+i); + } + if (i != len) abort (); +} + +static void +cbc_dec (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + int i, r; + unsigned char tmp[B]; + memcpy (tmp, iv, B); + for (i = 0; i < len; i += B) { + r = aes_dec_blk (in + i, tmp, &dctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + xor (tmp, tmp, iv); + iv = in + i; + memcpy (out + i, tmp, B); + } + if (i != len) abort (); +} + +static void +cts_enc (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + int r; + unsigned int len2; + unsigned char pn1[B], pn[B], cn[B], cn1[B]; + + if (len < B + 1) abort (); + len2 = (len - B - 1) & ~(B-1); + cbc_enc (out, in, iv, len2); + out += len2; + in += len2; + len -= len2; + if (len2) + iv = out - B; + if (len <= B || len > 2 * B) + abort (); + printf ("(did CBC mode for %d)\n", len2); + + D(in); + xor (pn1, in, iv); + D(pn1); + r = aes_enc_blk (pn1, cn, &ctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + D(cn); + memset (pn, 0, sizeof(pn)); + memcpy (pn, in+B, len-B); + D(pn); + xor (pn, pn, cn); + D(pn); + r = aes_enc_blk (pn, cn1, &ctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + D(cn1); + memcpy(out, cn1, B); + memcpy(out+B, cn, len-B); +} + +static void +cts_dec (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + int r; + unsigned int len2; + unsigned char pn1[B], pn[B], cn[B], cn1[B]; + + if (len < B + 1) abort (); + len2 = (len - B - 1) & ~(B-1); + cbc_dec (out, in, iv, len2); + out += len2; + in += len2; + len -= len2; + if (len2) + iv = in - B; + if (len <= B || len > 2 * B) + abort (); + + memcpy (cn1, in, B); + r = aes_dec_blk (cn1, pn, &dctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + memset (cn, 0, sizeof(cn)); + memcpy (cn, in+B, len-B); + xor (pn, pn, cn); + memcpy (cn+len-B, pn+len-B, 2*B-len); + r = aes_dec_blk (cn, pn1, &dctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + xor (pn1, pn1, iv); + memcpy(out, pn1, B); + memcpy(out+B, pn, len-B); +} + +static void ecb_test () +{ + int testno; + unsigned char tmp[4*B]; + + printf ("ECB tests:\n"); + printf ("key:"); + hexdump (key, sizeof(key)); + for (testno = 0; testno < NTESTS; testno++) { + unsigned len = (test_case_len[testno] + 15) & ~15; + printf ("\ntest %d - %d bytes\n", testno, len); + printf ("input:"); + hexdump (test_case[testno].input, len); + printf ("\n"); + ecb_enc (test_case[testno].output, test_case[testno].input, len); + printf ("output:"); + hexdump (test_case[testno].output, len); + printf ("\n"); + ecb_dec (tmp, test_case[testno].output, len); + if (memcmp (tmp, test_case[testno].input, len)) { + printf ("ecb decrypt failed!!"); + hexdump (tmp, len); + printf ("\n"); + exit (1); + } + } + printf ("\n"); +} + +unsigned char ivec[16] = { 0 }; + +static void cbc_test () +{ + int testno; + unsigned char tmp[4*B]; + + printf ("CBC tests:\n"); + printf ("initial vector:"); + hexdump (ivec, sizeof(ivec)); + for (testno = 0; testno < NTESTS; testno++) { + unsigned len = (test_case_len[testno] + 15) & ~15; + printf ("\ntest %d - %d bytes\n", testno, len); + printf ("input:"); + hexdump (test_case[testno].input, len); + printf ("\n"); + cbc_enc (test_case[testno].output, test_case[testno].input, ivec, len); + printf ("output:"); + hexdump (test_case[testno].output, len); + printf ("\n"); + cbc_dec (tmp, test_case[testno].output, ivec, len); + if (memcmp (tmp, test_case[testno].input, len)) { + printf("cbc decrypt failed!!"); + hexdump (tmp, len); + printf ("\n"); + exit(1); + } + } + printf ("\n"); +} + +static void cts_test () +{ + int testno; + unsigned char tmp[4*B]; + + printf ("CTS tests:\n"); + printf ("initial vector:"); + hexdump (ivec, sizeof(ivec)); + for (testno = 0; testno < NTESTS; testno++) { + unsigned int len = test_case_len[testno]; + printf ("\ntest %d - %d bytes\n", testno, len); + printf ("input:"); + hexdump (test_case[testno].input, len); + printf ("\n"); + cts_enc (test_case[testno].output, test_case[testno].input, ivec, len); + printf ("output:"); + hexdump (test_case[testno].output, len); + printf ("\n"); + cts_dec (tmp, test_case[testno].output, ivec, len); + if (memcmp (tmp, test_case[testno].input, len)) + fprintf (stderr, "cts decrypt failed!!\n"), exit(1); + } + printf ("\n"); +} + +int main () +{ + init (); + fips_test (); + + ecb_test(); + cbc_test(); + cts_test(); + + return 0; +} diff --git a/src/lib/crypto/builtin/aes/aes.h b/src/lib/crypto/builtin/aes/aes.h new file mode 100644 index 0000000..ac1c1b8 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aes.h @@ -0,0 +1,97 @@ +/* + ------------------------------------------------------------------------- + Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explcit or implied warranties + in respect of any properties, including, but not limited to, correctness + and fitness for purpose. + ------------------------------------------------------------------------- + Issue Date: 21/01/2002 + + This file contains the definitions required to use AES (Rijndael) in C. +*/ + +#ifndef _AES_H +#define _AES_H + +#include "uitypes.h" + +/* BLOCK_SIZE is in BYTES: 16, 24, 32 or undefined for aes.c and 16, 20, + 24, 28, 32 or undefined for aespp.c. When left undefined a slower + version that provides variable block length is compiled. +*/ + +#define BLOCK_SIZE 16 + +/* key schedule length (in 32-bit words) */ + +#if !defined(BLOCK_SIZE) +#define KS_LENGTH 128 +#else +#define KS_LENGTH 4 * BLOCK_SIZE +#endif + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef uint16_t aes_fret; /* type for function return value */ +#define aes_bad 0 /* bad function return value */ +#define aes_good 1 /* good function return value */ +#ifndef AES_DLL /* implement normal or DLL functions */ +#define aes_rval aes_fret +#else +#define aes_rval aes_fret __declspec(dllexport) _stdcall +#endif + +typedef struct /* the AES context for encryption */ +{ uint32_t k_sch[KS_LENGTH]; /* the encryption key schedule */ + uint32_t n_rnd; /* the number of cipher rounds */ + uint32_t n_blk; /* the number of bytes in the state */ +} aes_ctx; + +/* for Kerberos 5 tree -- hide names! */ +#define aes_blk_len krb5int_aes_blk_len +#define aes_enc_key krb5int_aes_enc_key +#define aes_enc_blk krb5int_aes_enc_blk +#define aes_dec_key krb5int_aes_dec_key +#define aes_dec_blk krb5int_aes_dec_blk +#define fl_tab krb5int_fl_tab +#define ft_tab krb5int_ft_tab +#define il_tab krb5int_il_tab +#define im_tab krb5int_im_tab +#define it_tab krb5int_it_tab +#define rcon_tab krb5int_rcon_tab + +aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]); + +aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); +aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); + +aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); +aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/src/lib/crypto/builtin/aes/aes.txt b/src/lib/crypto/builtin/aes/aes.txt new file mode 100644 index 0000000..b644b5e --- /dev/null +++ b/src/lib/crypto/builtin/aes/aes.txt @@ -0,0 +1,70 @@ + +An AES (Rijndael) Implementation in C/C++ (as specified in FIPS-197) +-------------------------------------------------------------------- + +The source code files are as follows: + +1. aes.h: the header file required to use AES in C +2. aescpp.h the header file required to use AES in C++ +3. aescrypt.c the main C source code file for encryption and decryption +4. aeskey.c the main C source code file for the key schedule +5. aestab.c the main file for the AES tables +6. aesopt.h the file for common code and for setting build options +7. aescrypt.asm a faster alternative to 3 above in assembler (using NASM) +8. uitypes.h a file for defining fixed length unsigned integer types +9. aescrypp.c an alternative to 3 for all Rijndael block and key sizes +10.aeskeypp.c an alternative to 4 for all Rijndael block and key sizes +11.aesxam.c an example of AES use + +Source files 9 and 10 are much slower than 4 and 5 for normal use and +should not be used unless support for 20 and 28 byte blocks and keys +is necessary. Files 4 and 5 provide support for block and key sizes +of 16, 24 and 32 bytes (fixed or variable) but the assemler code in +file 7 only supports the 16 byte AES block length. It does, however, +offer the three key sizes when used with file 4. The use of files 4 +and 5 (or 9 and 10) with variable block size should be avoided since +the code is much faster when the block size is fixed. + +The VC++ AES Development Project +-------------------------------- + +The VC++ SOlution contains the following sub-projects + +1. aes_asm this project tests the assembler code implementation +2. aes_dll this project builds the DLL version +3. aes_gav this project re-creates the test vector files and + optionally checks them against a reference set +4. aes_rav this project checks the values produced by the code + against the values in the test vector files +5. aes_tmr this project measures the speed of the code +6. aes_tst this project is set up to test the extended version + of Rijndael with block and key sizes of 16, 20, 24, + 28 and 32 bytes +7. aes_xam this project builds the example of AES use in a + simple file encryption program + +Note that the paths for the various directories have to be set up in +aestst.h + +The AES and Rijndael Test Vector Files +-------------------------------------- + +These files fall in the following groups (where <nn> is a two digit +number): + +1. ecbvk<nn>.txt ECB vectors with variable key +2. ecbvt<nn>.txt ECB vectors with variable text +3. ecbnk<nn>.txt new ECB vectors with variable key +4. ecbnt<nn>.txt new ECB vectors with variable text +5. ecbme<nn>.txt ECB monte carlo encryption test vectors +6. ecbmd<nn>.txt ECB monte carlo decryption test vectors +7. cbcme<nn>.txt CBC monte carlo encryption test vectors +8. cbcmd<nn>.txt CBC monte carlo decryption test vectors + +The first digit of the numeric suffix on the filename gives the +block size in 32bit units and the second numeric digit gives the +key size. For example, the file ecbvk44.txt provides the test +vectors for ECB encryption with a 128 bit block size and a 128 +bit key size. + + Brian Gladman <brg@gladman.uk.net>
\ No newline at end of file diff --git a/src/lib/crypto/builtin/aes/aes_s2k.c b/src/lib/crypto/builtin/aes/aes_s2k.c new file mode 100644 index 0000000..36045ed --- /dev/null +++ b/src/lib/crypto/builtin/aes/aes_s2k.c @@ -0,0 +1,90 @@ +/* + * lib/crypto/aes/aes_s2k.c + * + * Copyright 2003 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * krb5int_aes_string_to_key + */ + +#include "k5-int.h" +#include "dk.h" +#include "aes_s2k.h" + +#define DEFAULT_ITERATION_COUNT 4096 /* was 0xb000L in earlier drafts */ +#define MAX_ITERATION_COUNT 0x1000000L + +krb5_error_code +krb5int_aes_string_to_key(const struct krb5_enc_provider *enc, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key) +{ + unsigned long iter_count; + krb5_data out; + static const krb5_data usage = { KV5M_DATA, 8, "kerberos" }; + krb5_error_code err; + + if (params) { + unsigned char *p = (unsigned char *) params->data; + if (params->length != 4) + return KRB5_ERR_BAD_S2K_PARAMS; + /* The first two need casts in case 'int' is 16 bits. */ + iter_count = load_32_be(p); + if (iter_count == 0) { + iter_count = (1UL << 16) << 16; + if (((iter_count >> 16) >> 16) != 1) + return KRB5_ERR_BAD_S2K_PARAMS; + } + } else + iter_count = DEFAULT_ITERATION_COUNT; + + /* This is not a protocol specification constraint; this is an + implementation limit, which should eventually be controlled by + a config file. */ + if (iter_count >= MAX_ITERATION_COUNT) + return KRB5_ERR_BAD_S2K_PARAMS; + + /* + * Dense key space, no parity bits or anything, so take a shortcut + * and use the key contents buffer for the generated bytes. + */ + out.data = (char *) key->contents; + out.length = key->length; + if (out.length != 16 && out.length != 32) + return KRB5_CRYPTO_INTERNAL; + + err = krb5int_pbkdf2_hmac_sha1 (&out, iter_count, string, salt); + if (err) { + memset(out.data, 0, out.length); + return err; + } + + err = krb5_derive_key (enc, key, key, &usage); + if (err) { + memset(out.data, 0, out.length); + return err; + } + return 0; +} diff --git a/src/lib/crypto/builtin/aes/aes_s2k.h b/src/lib/crypto/builtin/aes/aes_s2k.h new file mode 100644 index 0000000..b6804a9 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aes_s2k.h @@ -0,0 +1,4 @@ +extern krb5_error_code +krb5int_aes_string_to_key (const struct krb5_enc_provider *, + const krb5_data *, const krb5_data *, + const krb5_data *, krb5_keyblock *key); diff --git a/src/lib/crypto/builtin/aes/aescpp.h b/src/lib/crypto/builtin/aes/aescpp.h new file mode 100644 index 0000000..e685485 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aescpp.h @@ -0,0 +1,55 @@ + +/* + ------------------------------------------------------------------------- + Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK. + All rights reserved. + + TERMS + + Redistribution and use in source and binary forms, with or without + modification, are permitted subject to the following conditions: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The copyright holder's name must not be used to endorse or promote + any products derived from this software without his specific prior + written permission. + + This software is provided 'as is' with no express or implied warranties + of correctness or fitness for purpose. + ------------------------------------------------------------------------- + Issue Date: 21/01/2002 + + This file contains the definitions required to use AES (Rijndael) in C++. +*/ + +#ifndef _AESCPP_H +#define _AESCPP_H + +#include "aes.h" + +class AESclass +{ aes_ctx cx[1]; +public: +#if defined(BLOCK_SIZE) + AESclass() { cx->n_blk = BLOCK_SIZE; cx->n_rnd = 0; } +#else + AESclass(unsigned int blen = 16) { cx->n_blk = blen; cx->n_rnd = 0; } +#endif + aes_rval blk_len(unsigned int blen) { return aes_blk_len(blen, cx); } + aes_rval enc_key(const unsigned char in_key[], unsigned int klen) + { return aes_enc_key(in_key, klen, cx); } + aes_rval dec_key(const unsigned char in_key[], unsigned int klen) + { return aes_dec_key(in_key, klen, cx); } + aes_rval enc_blk(const unsigned char in_blk[], unsigned char out_blk[]) + { return aes_enc_blk(in_blk, out_blk, cx); } + aes_rval dec_blk(const unsigned char in_blk[], unsigned char out_blk[]) + { return aes_dec_blk(in_blk, out_blk, cx); } +}; + +#endif diff --git a/src/lib/crypto/builtin/aes/aescrypp.c b/src/lib/crypto/builtin/aes/aescrypp.c new file mode 100644 index 0000000..87b6341 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aescrypp.c @@ -0,0 +1,487 @@ +/* + ------------------------------------------------------------------------- + Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explcit or implied warranties + in respect of any properties, including, but not limited to, correctness + and fitness for purpose. + ------------------------------------------------------------------------- + Issue Date: 21/01/2002 + + This file contains the code for implementing encryption and decryption + for AES (Rijndael) for block and key sizes of 16, 20, 24, 28 and 32 bytes. + It can optionally be replaced by code written in assembler using NASM. +*/ + +#include "aesopt.h" + +#define unused 77 /* Sunset Strip */ + +#define si(y,x,k,c) s(y,c) = word_in(x + 4 * c) ^ k[c] +#define so(y,x,c) word_out(y + 4 * c, s(x,c)) + +#if BLOCK_SIZE == 16 + +#if defined(ARRAYS) +#define locals(y,x) x[4],y[4] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 + /* + the following defines prevent the compiler requiring the declaration + of generated but unused variables in the fwd_var and inv_var macros + */ +#define b04 unused +#define b05 unused +#define b06 unused +#define b07 unused +#define b14 unused +#define b15 unused +#define b16 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) + +#elif BLOCK_SIZE == 20 + +#if defined(ARRAYS) +#define locals(y,x) x[5],y[5] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,x##4,y##0,y##1,y##2,y##3,y##4 +#define b05 unused +#define b06 unused +#define b07 unused +#define b15 unused +#define b16 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); s(y,4) = s(x,4); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); si(y,x,k,4) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); so(y,x,4) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); rm(y,x,k,4) + +#elif BLOCK_SIZE == 24 + +#if defined(ARRAYS) +#define locals(y,x) x[6],y[6] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5, \ + y##0,y##1,y##2,y##3,y##4,y##5 +#define b06 unused +#define b07 unused +#define b16 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); \ + s(y,4) = s(x,4); s(y,5) = s(x,5); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \ + si(y,x,k,3); si(y,x,k,4); si(y,x,k,5) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \ + so(y,x,3); so(y,x,4); so(y,x,5) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \ + rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5) + +#elif BLOCK_SIZE == 28 + +#if defined(ARRAYS) +#define locals(y,x) x[7],y[7] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6 \ + y##0,y##1,y##2,y##3,y##4,y##5,y##6 +#define b07 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); \ + s(y,4) = s(x,4); s(y,5) = s(x,5);; s(y,6) = s(x,6); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \ + si(y,x,k,3); si(y,x,k,4); si(y,x,k,5); si(y,x,k,6) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \ + so(y,x,3); so(y,x,4); so(y,x,5); so(y,x,6) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \ + rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6) +#else + +#if defined(ARRAYS) +#define locals(y,x) x[8],y[8] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \ + y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7 +#endif +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); \ + s(y,4) = s(x,4); s(y,5) = s(x,5); \ + s(y,6) = s(x,6); s(y,7) = s(x,7); + +#if BLOCK_SIZE == 32 + +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \ + si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \ + so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \ + rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7) +#else + +#define state_in(y,x,k) \ +switch(nc) \ +{ case 8: si(y,x,k,7); \ + case 7: si(y,x,k,6); \ + case 6: si(y,x,k,5); \ + case 5: si(y,x,k,4); \ + case 4: si(y,x,k,3); si(y,x,k,2); \ + si(y,x,k,1); si(y,x,k,0); \ +} + +#define state_out(y,x) \ +switch(nc) \ +{ case 8: so(y,x,7); \ + case 7: so(y,x,6); \ + case 6: so(y,x,5); \ + case 5: so(y,x,4); \ + case 4: so(y,x,3); so(y,x,2); \ + so(y,x,1); so(y,x,0); \ +} + +#if defined(FAST_VARIABLE) + +#define round(rm,y,x,k) \ +switch(nc) \ +{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ + rm(y,x,k,5); rm(y,x,k,4); \ + rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ + break; \ + case 7: rm(y,x,k,6); rm(y,x,k,5); \ + rm(y,x,k,4); rm(y,x,k,3); \ + rm(y,x,k,2); rm(y,x,k,1); \ + rm(y,x,k,0); \ + break; \ + case 6: rm(y,x,k,5); rm(y,x,k,4); \ + rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ + break; \ + case 5: rm(y,x,k,4); rm(y,x,k,3); \ + rm(y,x,k,2); rm(y,x,k,1); \ + rm(y,x,k,0); \ + break; \ + case 4: rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ + break; \ +} +#else + +#define round(rm,y,x,k) \ +switch(nc) \ +{ case 8: rm(y,x,k,7); \ + case 7: rm(y,x,k,6); \ + case 6: rm(y,x,k,5); \ + case 5: rm(y,x,k,4); \ + case 4: rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ +} + +#endif + +#endif +#endif + +#if defined(ENCRYPTION) + +/* I am grateful to Frank Yellin for the following construction + (and that for decryption) which, given the column (c) of the + output state variable, gives the input state variables which + are needed for each row (r) of the state. + + For the fixed block size options, compilers should reduce these + two expressions to fixed variable references. But for variable + block size code conditional clauses will sometimes be returned. + + y = output word, x = input word, r = row, c = column for r = 0, + 1, 2 and 3 = column accessed for row r. +*/ + +#define fwd_var(x,r,c) \ + ( r==0 ? \ + ( c==0 ? s(x,0) \ + : c==1 ? s(x,1) \ + : c==2 ? s(x,2) \ + : c==3 ? s(x,3) \ + : c==4 ? s(x,4) \ + : c==5 ? s(x,5) \ + : c==6 ? s(x,6) \ + : s(x,7)) \ + : r==1 ? \ + ( c==0 ? s(x,1) \ + : c==1 ? s(x,2) \ + : c==2 ? s(x,3) \ + : c==3 ? nc==4 ? s(x,0) : s(x,4) \ + : c==4 ? nc==5 ? s(x,0) : s(x,5) \ + : c==5 ? nc==6 ? s(x,0) : s(x,6) \ + : c==6 ? nc==7 ? s(x,0) : s(x,7) \ + : s(x,0)) \ + : r==2 ? \ + ( c==0 ? nc==8 ? s(x,3) : s(x,2) \ + : c==1 ? nc==8 ? s(x,4) : s(x,3) \ + : c==2 ? nc==8 ? s(x,5) : nc==4 ? s(x,0) : s(x,4) \ + : c==3 ? nc==8 ? s(x,6) : nc==5 ? s(x,0) : nc==4 ? s(x,1) : s(x,5) \ + : c==4 ? nc==8 ? s(x,7) : nc==7 ? s(x,6) : nc==6 ? s(x,0) : s(x,1) \ + : c==5 ? nc==6 ? s(x,1) : s(x,0) \ + : c==6 ? s(x,1) \ + : s(x,2)) \ + : \ + ( c==0 ? nc>6 ? s(x,4) : s(x,3) \ + : c==1 ? nc>6 ? s(x,5) : nc==4 ? s(x,0) : s(x,4) \ + : c==2 ? nc>6 ? s(x,6) : nc==6 ? s(x,5) : nc==5 ? s(x,0) : s(x,1) \ + : c==3 ? nc==8 ? s(x,7) : nc==5 ? s(x,1) : nc==4 ? s(x,2) : s(x,0) \ + : c==4 ? nc==8 ? s(x,0) : nc==5 ? s(x,2) : s(x,1) \ + : c==5 ? nc==8 ? s(x,1) : s(x,2) \ + : c==6 ? nc==8 ? s(x,2) : s(x,3) \ + : s(x,3))) + +#if defined(FT4_SET) +#undef dec_fmvars +#define dec_fmvars +#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c) +#elif defined(FT1_SET) +#undef dec_fmvars +#define dec_fmvars +#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c) +#else +#define fwd_rnd(y,x,k,c) s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c] +#endif + +#if defined(FL4_SET) +#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c) +#elif defined(FL1_SET) +#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c) +#else +#define fwd_lrnd(y,x,k,c) s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c] +#endif + +aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) +{ uint32_t locals(b0, b1); + const uint32_t *kp = cx->k_sch; + dec_fmvars /* declare variables for fwd_mcol() if needed */ + + if(!(cx->n_blk & 1)) return aes_bad; + +#if (ENC_UNROLL == FULL) + + state_in((cx->n_rnd & 1 ? b1 : b0), in_blk, kp); + kp += (cx->n_rnd - 9) * nc; + + switch(cx->n_rnd) + { + case 14: round(fwd_rnd, b1, b0, kp - 4 * nc); + case 13: round(fwd_rnd, b0, b1, kp - 3 * nc); + case 12: round(fwd_rnd, b1, b0, kp - 2 * nc); + case 11: round(fwd_rnd, b0, b1, kp - nc); + case 10: round(fwd_rnd, b1, b0, kp ); + round(fwd_rnd, b0, b1, kp + nc); + round(fwd_rnd, b1, b0, kp + 2 * nc); + round(fwd_rnd, b0, b1, kp + 3 * nc); + round(fwd_rnd, b1, b0, kp + 4 * nc); + round(fwd_rnd, b0, b1, kp + 5 * nc); + round(fwd_rnd, b1, b0, kp + 6 * nc); + round(fwd_rnd, b0, b1, kp + 7 * nc); + round(fwd_rnd, b1, b0, kp + 8 * nc); + round(fwd_lrnd, b0, b1, kp + 9 * nc); + } +#else + { uint32_t rnd; + + state_in(b0, in_blk, kp); + +#if (ENC_UNROLL == PARTIAL) + + for(rnd = 0; rnd < (cx->n_rnd - 1) >> 1; ++rnd) + { + kp += nc; + round(fwd_rnd, b1, b0, kp); + kp += nc; + round(fwd_rnd, b0, b1, kp); + } + + if(cx->n_rnd & 1) + { + l_copy(b1, b0); + } + else + { + kp += nc; + round(fwd_rnd, b1, b0, kp); + } +#else + for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd) + { + kp += nc; + round(fwd_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp += nc; + round(fwd_lrnd, b0, b1, kp); + } +#endif + + state_out(out_blk, b0); + return aes_good; +} + +#endif + +#if defined(DECRYPTION) + +#define inv_var(x,r,c) \ + ( r==0 ? \ + ( c==0 ? s(x,0) \ + : c==1 ? s(x,1) \ + : c==2 ? s(x,2) \ + : c==3 ? s(x,3) \ + : c==4 ? s(x,4) \ + : c==5 ? s(x,5) \ + : c==6 ? s(x,6) \ + : s(x,7)) \ + : r==1 ? \ + ( c==0 ? nc==8 ? s(x,7) : nc==7 ? s(x,6) : nc==6 ? s(x,5) : nc==5 ? s(x,4) : s(x,3) \ + : c==1 ? s(x,0) \ + : c==2 ? s(x,1) \ + : c==3 ? s(x,2) \ + : c==4 ? s(x,3) \ + : c==5 ? s(x,4) \ + : c==6 ? s(x,5) \ + : s(x,6)) \ + : r==2 ? \ + ( c==0 ? nc>6 ? s(x,5) : nc==6 ? s(x,4) : nc==5 ? s(x,3) : s(x,2) \ + : c==1 ? nc>6 ? s(x,6) : nc==6 ? s(x,5) : nc==5 ? s(x,4) : s(x,3) \ + : c==2 ? nc==8 ? s(x,7) : s(x,0) \ + : c==3 ? nc==8 ? s(x,0) : s(x,1) \ + : c==4 ? nc==8 ? s(x,1) : s(x,2) \ + : c==5 ? nc==8 ? s(x,2) : s(x,3) \ + : c==6 ? nc==8 ? s(x,3) : s(x,4) \ + : s(x,4)) \ + : \ + ( c==0 ? nc==8 ? s(x,4) : nc==5 ? s(x,2) : nc==4 ? s(x,1) : s(x,3) \ + : c==1 ? nc==8 ? s(x,5) : nc==5 ? s(x,3) : nc==4 ? s(x,2) : s(x,4) \ + : c==2 ? nc==8 ? s(x,6) : nc==5 ? s(x,4) : nc==4 ? s(x,3) : s(x,5) \ + : c==3 ? nc==8 ? s(x,7) : nc==7 ? s(x,6) : s(x,0) \ + : c==4 ? nc>6 ? s(x,0) : s(x,1) \ + : c==5 ? nc==6 ? s(x,2) : s(x,1) \ + : c==6 ? s(x,2) \ + : s(x,3))) + +#if defined(IT4_SET) +#undef dec_imvars +#define dec_imvars +#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c) +#elif defined(IT1_SET) +#undef dec_imvars +#define dec_imvars +#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c) +#else +#define inv_rnd(y,x,k,c) s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]) +#endif + +#if defined(IL4_SET) +#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c) +#elif defined(IL1_SET) +#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c) +#else +#define inv_lrnd(y,x,k,c) s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c] +#endif + +aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) +{ uint32_t locals(b0, b1); + const uint32_t *kp = cx->k_sch + nc * cx->n_rnd; + dec_imvars /* declare variables for inv_mcol() if needed */ + + if(!(cx->n_blk & 2)) return aes_bad; + +#if (DEC_UNROLL == FULL) + + state_in((cx->n_rnd & 1 ? b1 : b0), in_blk, kp); + kp = cx->k_sch + 9 * nc; + + switch(cx->n_rnd) + { + case 14: round(inv_rnd, b1, b0, kp + 4 * nc); + case 13: round(inv_rnd, b0, b1, kp + 3 * nc); + case 12: round(inv_rnd, b1, b0, kp + 2 * nc); + case 11: round(inv_rnd, b0, b1, kp + nc); + case 10: round(inv_rnd, b1, b0, kp ); + round(inv_rnd, b0, b1, kp - nc); + round(inv_rnd, b1, b0, kp - 2 * nc); + round(inv_rnd, b0, b1, kp - 3 * nc); + round(inv_rnd, b1, b0, kp - 4 * nc); + round(inv_rnd, b0, b1, kp - 5 * nc); + round(inv_rnd, b1, b0, kp - 6 * nc); + round(inv_rnd, b0, b1, kp - 7 * nc); + round(inv_rnd, b1, b0, kp - 8 * nc); + round(inv_lrnd, b0, b1, kp - 9 * nc); + } +#else + { uint32_t rnd; + + state_in(b0, in_blk, kp); + +#if (DEC_UNROLL == PARTIAL) + + for(rnd = 0; rnd < (cx->n_rnd - 1) >> 1; ++rnd) + { + kp -= nc; + round(inv_rnd, b1, b0, kp); + kp -= nc; + round(inv_rnd, b0, b1, kp); + } + + if(cx->n_rnd & 1) + { + l_copy(b1, b0); + } + else + { + kp -= nc; + round(inv_rnd, b1, b0, kp); + } +#else + for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd) + { + kp -= nc; + round(inv_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp -= nc; + round(inv_lrnd, b0, b1, kp); + } +#endif + + state_out(out_blk, b0); + return aes_good; +} + +#endif diff --git a/src/lib/crypto/builtin/aes/aescrypt.asm b/src/lib/crypto/builtin/aes/aescrypt.asm new file mode 100644 index 0000000..35a6818 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aescrypt.asm @@ -0,0 +1,402 @@ + +; ------------------------------------------------------------------------- +; Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK. +; All rights reserved. +; +; LICENSE TERMS +; +; The free distribution and use of this software in both source and binary +; form is allowed (with or without changes) provided that: +; +; 1. distributions of this source code include the above copyright +; notice, this list of conditions and the following disclaimer; +; +; 2. distributions in binary form include the above copyright +; notice, this list of conditions and the following disclaimer +; in the documentation and/or other associated materials; +; +; 3. the copyright holder's name is not used to endorse products +; built using this software without specific written permission. +; +; DISCLAIMER +; +; This software is provided 'as is' with no explcit or implied warranties +; in respect of any properties, including, but not limited to, correctness +; and fitness for purpose. +; ------------------------------------------------------------------------- +; Issue Date: 15/01/2002 + +; An AES (Rijndael) implementation for the Pentium MMX family using the NASM +; assembler <http://www.web-sites.co.uk/nasm/>. This version only implements +; the standard AES block length (128 bits, 16 bytes) with the same interface +; as that used in my C/C++ implementation. This code does not preserve the +; eax, ecx or edx registers or the artihmetic status flags. However, the ebx, +; esi, edi, and ebp registers are preserved across calls. Only encryption +; and decryption are implemented here, the key schedule code being that from +; compiling aes.c with USE_ASM defined. This code uses VC++ register saving +; conentions; if it is used with another compiler, its conventions for using +; and saving registers will need to be checked. + + section .text use32 + +; aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); +; aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); + + global _aes_enc_blk + global _aes_dec_blk + + extern _ft_tab + extern _fl_tab + extern _it_tab + extern _il_tab + +;%define USE_MMX ; include this to use MMX registers for temporary storage +;%define USE_EMMS ; include this if you make use of floating point operations + +%ifdef USE_MMX +%ifdef USE_EMMS +%define EMMS_ON +%endif +%endif + +tlen: equ 1024 ; length of each of 4 'xor' arrays (256 32-bit words) + +; offsets to parameters with one register pushed onto stack + +in_blk: equ 8 ; input byte array address parameter +out_blk:equ 12 ; output byte array address parameter +ctx: equ 16 ; AES context structure + +; offsets in context structure + +ksch: equ 0 ; encryption key schedule base address +nrnd: equ 256 ; number of rounds +nblk: equ 260 ; number of rounds + +; register mapping for encrypt and decrypt subroutines + +%define r0 eax +%define r1 ebx +%define r2 ecx +%define r3 edx +%define r4 esi +%define r5 edi +%define r6 ebp + +%define eaxl al +%define eaxh ah +%define ebxl bl +%define ebxh bh +%define ecxl cl +%define ecxh ch +%define edxl dl +%define edxh dh + +; This macro takes a 32-bit word representing a column and uses +; each of its four bytes to index into four tables of 256 32-bit +; words to obtain values that are then xored into the appropriate +; output registers r0, r1, r4 or r5. + +; Parameters: +; %1 out_state[0] +; %2 out_state[1] +; %3 out_state[2] +; %4 out_state[3] +; %5 table base address +; %6 input register for the round (destroyed) +; %7 scratch register for the round + +%macro do_col 7 + + movzx %7,%6l + xor %1,[4*%7+%5] + movzx %7,%6h + shr %6,16 + xor %2,[4*%7+%5+tlen] + movzx %7,%6l + movzx %6,%6h + xor %3,[4*%7+%5+2*tlen] + xor %4,[4*%6+%5+3*tlen] + +%endmacro + +; initialise output registers from the key schedule + +%macro do_fcol 8 + + mov %1,[%8] + movzx %7,%6l + mov %2,[%8+12] + xor %1,[4*%7+%5] + mov %4,[%8+ 4] + movzx %7,%6h + shr %6,16 + xor %2,[4*%7+%5+tlen] + movzx %7,%6l + movzx %6,%6h + xor %4,[4*%6+%5+3*tlen] + mov %6,%3 + mov %3,[%8+ 8] + xor %3,[4*%7+%5+2*tlen] + +%endmacro + +; initialise output registers from the key schedule + +%macro do_icol 8 + + mov %1,[%8] + movzx %7,%6l + mov %2,[%8+ 4] + xor %1,[4*%7+%5] + mov %4,[%8+12] + movzx %7,%6h + shr %6,16 + xor %2,[4*%7+%5+tlen] + movzx %7,%6l + movzx %6,%6h + xor %4,[4*%6+%5+3*tlen] + mov %6,%3 + mov %3,[%8+ 8] + xor %3,[4*%7+%5+2*tlen] + +%endmacro + +; These macros implement either MMX or stack based local variables + +%ifdef USE_MMX + +%macro save 2 + movd mm%1,%2 +%endmacro + +%macro restore 2 + movd %1,mm%2 +%endmacro + +%else + +%macro save 2 + mov [esp+4*%1],%2 +%endmacro + +%macro restore 2 + mov %1,[esp+4*%2] +%endmacro + +%endif + +; This macro performs a forward encryption cycle. It is entered with +; the first previous round column values in r0, r1, r4 and r5 and +; exits with the final values in the same registers, using the MMX +; registers mm0-mm1 for temporary storage + +%macro fwd_rnd 1-2 _ft_tab + +; mov current column values into the MMX registers + + mov r2,r0 + save 0,r1 + save 1,r5 + +; compute new column values + + do_fcol r0,r5,r4,r1, %2, r2,r3, %1 + do_col r4,r1,r0,r5, %2, r2,r3 + restore r2,0 + do_col r1,r0,r5,r4, %2, r2,r3 + restore r2,1 + do_col r5,r4,r1,r0, %2, r2,r3 + +%endmacro + +; This macro performs an inverse encryption cycle. It is entered with +; the first previous round column values in r0, r1, r4 and r5 and +; exits with the final values in the same registers, using the MMX +; registers mm0-mm1 for temporary storage + +%macro inv_rnd 1-2 _it_tab + +; mov current column values into the MMX registers + + mov r2,r0 + save 0,r1 + save 1,r5 + +; compute new column values + + do_icol r0,r1,r4,r5, %2, r2,r3, %1 + do_col r4,r5,r0,r1, %2, r2,r3 + restore r2,0 + do_col r1,r4,r5,r0, %2, r2,r3 + restore r2,1 + do_col r5,r0,r1,r4, %2, r2,r3 + +%endmacro + +; AES (Rijndael) Encryption Subroutine + +_aes_enc_blk: + push ebp + mov ebp,[esp+ctx] ; pointer to context + xor eax,eax + test [ebp+nblk],byte 1 + je .0 + cmp eax,[ebp+nrnd] ; encryption/decryption flags + jne short .1 +.0: pop ebp + ret + +; CAUTION: the order and the values used in these assigns +; rely on the register mappings + +.1: push ebx + mov r2,[esp+in_blk+4] + push esi + mov r3,[ebp+nrnd] ; number of rounds + push edi + lea r6,[ebp+ksch] ; key pointer + +; input four columns and xor in first round key + + mov r0,[r2] + mov r1,[r2+4] + mov r4,[r2+8] + mov r5,[r2+12] + xor r0,[r6] + xor r1,[r6+4] + xor r4,[r6+8] + xor r5,[r6+12] + +%ifndef USE_MMX + sub esp,8 ; space for register saves on stack +%endif + add r6,16 ; increment to next round key + sub r3,10 + je .4 ; 10 rounds for 128-bit key + add r6,32 + sub r3,2 + je .3 ; 12 rounds for 128-bit key + add r6,32 + +.2: fwd_rnd r6-64 ; 14 rounds for 128-bit key + fwd_rnd r6-48 +.3: fwd_rnd r6-32 ; 12 rounds for 128-bit key + fwd_rnd r6-16 +.4: fwd_rnd r6 ; 10 rounds for 128-bit key + fwd_rnd r6+ 16 + fwd_rnd r6+ 32 + fwd_rnd r6+ 48 + fwd_rnd r6+ 64 + fwd_rnd r6+ 80 + fwd_rnd r6+ 96 + fwd_rnd r6+112 + fwd_rnd r6+128 + fwd_rnd r6+144,_fl_tab ; last round uses a different table + +; move final values to the output array. CAUTION: the +; order of these assigns rely on the register mappings + +%ifndef USE_MMX + add esp,8 +%endif + mov r6,[esp+out_blk+12] + mov [r6+12],r5 + pop edi + mov [r6+8],r4 + pop esi + mov [r6+4],r1 + pop ebx + mov [r6],r0 + pop ebp + mov eax,1 +%ifdef EMMS_ON + emms +%endif + ret + +; AES (Rijndael) Decryption Subroutine + +_aes_dec_blk: + push ebp + mov ebp,[esp+ctx] ; pointer to context + xor eax,eax + test [ebp+nblk],byte 2 + je .0 + cmp eax,[ebp+nrnd] ; encryption/decryption flags + jne short .1 +.0: pop ebp + ret + +; CAUTION: the order and the values used in these assigns +; rely on the register mappings + +.1: push ebx + mov r2,[esp+in_blk+4] + push esi + mov r3,[ebp+nrnd] ; number of rounds + push edi + lea r6,[ebp+ksch] ; key pointer + mov r0,r3 + shl r0,4 + add r6,r0 + +; input four columns and xor in first round key + + mov r0,[r2] + mov r1,[r2+4] + mov r4,[r2+8] + mov r5,[r2+12] + xor r0,[r6] + xor r1,[r6+4] + xor r4,[r6+8] + xor r5,[r6+12] + +%ifndef USE_MMX + sub esp,8 ; space for register saves on stack +%endif + sub r6,16 ; increment to next round key + sub r3,10 + je .4 ; 10 rounds for 128-bit key + sub r6,32 + sub r3,2 + je .3 ; 12 rounds for 128-bit key + sub r6,32 + +.2: inv_rnd r6+64 ; 14 rounds for 128-bit key + inv_rnd r6+48 +.3: inv_rnd r6+32 ; 12 rounds for 128-bit key + inv_rnd r6+16 +.4: inv_rnd r6 ; 10 rounds for 128-bit key + inv_rnd r6- 16 + inv_rnd r6- 32 + inv_rnd r6- 48 + inv_rnd r6- 64 + inv_rnd r6- 80 + inv_rnd r6- 96 + inv_rnd r6-112 + inv_rnd r6-128 + inv_rnd r6-144,_il_tab ; last round uses a different table + +; move final values to the output array. CAUTION: the +; order of these assigns rely on the register mappings + +%ifndef USE_MMX + add esp,8 +%endif + mov r6,[esp+out_blk+12] + mov [r6+12],r5 + pop edi + mov [r6+8],r4 + pop esi + mov [r6+4],r1 + pop ebx + mov [r6],r0 + pop ebp + mov eax,1 +%ifdef EMMS_ON + emms +%endif + ret + + end diff --git a/src/lib/crypto/builtin/aes/aescrypt.c b/src/lib/crypto/builtin/aes/aescrypt.c new file mode 100644 index 0000000..9db66e2 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aescrypt.c @@ -0,0 +1,421 @@ +/* + ------------------------------------------------------------------------- + Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explcit or implied warranties + in respect of any properties, including, but not limited to, correctness + and fitness for purpose. + ------------------------------------------------------------------------- + Issue Date: 21/01/2002 + + This file contains the code for implementing encryption and decryption + for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It + can optionally be replaced by code written in assembler using NASM. +*/ + +#include "aesopt.h" + +#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7) +#error An illegal block size has been specified. +#endif + +#define unused 77 /* Sunset Strip */ + +#define si(y,x,k,c) s(y,c) = word_in(x + 4 * c) ^ k[c] +#define so(y,x,c) word_out(y + 4 * c, s(x,c)) + +#if BLOCK_SIZE == 16 + +#if defined(ARRAYS) +#define locals(y,x) x[4],y[4] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 + /* + the following defines prevent the compiler requiring the declaration + of generated but unused variables in the fwd_var and inv_var macros + */ +#define b04 unused +#define b05 unused +#define b06 unused +#define b07 unused +#define b14 unused +#define b15 unused +#define b16 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) + +#elif BLOCK_SIZE == 24 + +#if defined(ARRAYS) +#define locals(y,x) x[6],y[6] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5, \ + y##0,y##1,y##2,y##3,y##4,y##5 +#define b06 unused +#define b07 unused +#define b16 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); \ + s(y,4) = s(x,4); s(y,5) = s(x,5); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \ + si(y,x,k,3); si(y,x,k,4); si(y,x,k,5) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \ + so(y,x,3); so(y,x,4); so(y,x,5) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \ + rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5) +#else + +#if defined(ARRAYS) +#define locals(y,x) x[8],y[8] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \ + y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7 +#endif +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); \ + s(y,4) = s(x,4); s(y,5) = s(x,5); \ + s(y,6) = s(x,6); s(y,7) = s(x,7); + +#if BLOCK_SIZE == 32 + +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \ + si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \ + so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \ + rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7) +#else + +#define state_in(y,x,k) \ +switch(nc) \ +{ case 8: si(y,x,k,7); si(y,x,k,6); \ + case 6: si(y,x,k,5); si(y,x,k,4); \ + case 4: si(y,x,k,3); si(y,x,k,2); \ + si(y,x,k,1); si(y,x,k,0); \ +} + +#define state_out(y,x) \ +switch(nc) \ +{ case 8: so(y,x,7); so(y,x,6); \ + case 6: so(y,x,5); so(y,x,4); \ + case 4: so(y,x,3); so(y,x,2); \ + so(y,x,1); so(y,x,0); \ +} + +#if defined(FAST_VARIABLE) + +#define round(rm,y,x,k) \ +switch(nc) \ +{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ + rm(y,x,k,5); rm(y,x,k,4); \ + rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ + break; \ + case 6: rm(y,x,k,5); rm(y,x,k,4); \ + rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ + break; \ + case 4: rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ + break; \ +} +#else + +#define round(rm,y,x,k) \ +switch(nc) \ +{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ + case 6: rm(y,x,k,5); rm(y,x,k,4); \ + case 4: rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ +} + +#endif + +#endif +#endif + +#if defined(ENCRYPTION) + +/* I am grateful to Frank Yellin for the following construction + (and that for decryption) which, given the column (c) of the + output state variable, gives the input state variables which + are needed in its computation for each row (r) of the state. + + For the fixed block size options, compilers should be able to + reduce this complex expression (and the equivalent one for + decryption) to a static variable reference at compile time. + But for variable block size code, there will be some limbs on + which conditional clauses will be returned. +*/ + +/* y = output word, x = input word, r = row, c = column for r = 0, + 1, 2 and 3 = column accessed for row r. +*/ + +#define fwd_var(x,r,c) \ + ( r==0 ? \ + ( c==0 ? s(x,0) \ + : c==1 ? s(x,1) \ + : c==2 ? s(x,2) \ + : c==3 ? s(x,3) \ + : c==4 ? s(x,4) \ + : c==5 ? s(x,5) \ + : c==6 ? s(x,6) \ + : s(x,7)) \ + : r==1 ? \ + ( c==0 ? s(x,1) \ + : c==1 ? s(x,2) \ + : c==2 ? s(x,3) \ + : c==3 ? nc==4 ? s(x,0) : s(x,4) \ + : c==4 ? s(x,5) \ + : c==5 ? nc==8 ? s(x,6) : s(x,0) \ + : c==6 ? s(x,7) \ + : s(x,0)) \ + : r==2 ? \ + ( c==0 ? nc==8 ? s(x,3) : s(x,2) \ + : c==1 ? nc==8 ? s(x,4) : s(x,3) \ + : c==2 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \ + : c==3 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \ + : c==4 ? nc==8 ? s(x,7) : s(x,0) \ + : c==5 ? nc==8 ? s(x,0) : s(x,1) \ + : c==6 ? s(x,1) \ + : s(x,2)) \ + : \ + ( c==0 ? nc==8 ? s(x,4) : s(x,3) \ + : c==1 ? nc==4 ? s(x,0) : nc==8 ? s(x,5) : s(x,4) \ + : c==2 ? nc==4 ? s(x,1) : nc==8 ? s(x,6) : s(x,5) \ + : c==3 ? nc==4 ? s(x,2) : nc==8 ? s(x,7) : s(x,0) \ + : c==4 ? nc==8 ? s(x,0) : s(x,1) \ + : c==5 ? nc==8 ? s(x,1) : s(x,2) \ + : c==6 ? s(x,2) \ + : s(x,3))) + +#if defined(FT4_SET) +#undef dec_fmvars +#define dec_fmvars +#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c) +#elif defined(FT1_SET) +#undef dec_fmvars +#define dec_fmvars +#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c) +#else +#define fwd_rnd(y,x,k,c) s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c] +#endif + +#if defined(FL4_SET) +#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c) +#elif defined(FL1_SET) +#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c) +#else +#define fwd_lrnd(y,x,k,c) s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c] +#endif + +aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) +{ uint32_t locals(b0, b1); + const uint32_t *kp = cx->k_sch; + dec_fmvars /* declare variables for fwd_mcol() if needed */ + + if(!(cx->n_blk & 1)) return aes_bad; + + state_in(b0, in_blk, kp); + +#if (ENC_UNROLL == FULL) + + kp += (cx->n_rnd - 9) * nc; + + switch(cx->n_rnd) + { + case 14: round(fwd_rnd, b1, b0, kp - 4 * nc); + round(fwd_rnd, b0, b1, kp - 3 * nc); + case 12: round(fwd_rnd, b1, b0, kp - 2 * nc); + round(fwd_rnd, b0, b1, kp - nc); + case 10: round(fwd_rnd, b1, b0, kp ); + round(fwd_rnd, b0, b1, kp + nc); + round(fwd_rnd, b1, b0, kp + 2 * nc); + round(fwd_rnd, b0, b1, kp + 3 * nc); + round(fwd_rnd, b1, b0, kp + 4 * nc); + round(fwd_rnd, b0, b1, kp + 5 * nc); + round(fwd_rnd, b1, b0, kp + 6 * nc); + round(fwd_rnd, b0, b1, kp + 7 * nc); + round(fwd_rnd, b1, b0, kp + 8 * nc); + round(fwd_lrnd, b0, b1, kp + 9 * nc); + } +#else + +#if (ENC_UNROLL == PARTIAL) + { uint32_t rnd; + for(rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd) + { + kp += nc; + round(fwd_rnd, b1, b0, kp); + kp += nc; + round(fwd_rnd, b0, b1, kp); + } + kp += nc; + round(fwd_rnd, b1, b0, kp); +#else + { uint32_t rnd, *p0 = b0, *p1 = b1, *pt; + for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd) + { + kp += nc; + round(fwd_rnd, p1, p0, kp); + pt = p0, p0 = p1, p1 = pt; + } +#endif + kp += nc; + round(fwd_lrnd, b0, b1, kp); + } +#endif + + state_out(out_blk, b0); + return aes_good; +} + +#endif + +#if defined(DECRYPTION) + +#define inv_var(x,r,c) \ + ( r==0 ? \ + ( c==0 ? s(x,0) \ + : c==1 ? s(x,1) \ + : c==2 ? s(x,2) \ + : c==3 ? s(x,3) \ + : c==4 ? s(x,4) \ + : c==5 ? s(x,5) \ + : c==6 ? s(x,6) \ + : s(x,7)) \ + : r==1 ? \ + ( c==0 ? nc==4 ? s(x,3) : nc==8 ? s(x,7) : s(x,5) \ + : c==1 ? s(x,0) \ + : c==2 ? s(x,1) \ + : c==3 ? s(x,2) \ + : c==4 ? s(x,3) \ + : c==5 ? s(x,4) \ + : c==6 ? s(x,5) \ + : s(x,6)) \ + : r==2 ? \ + ( c==0 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \ + : c==1 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \ + : c==2 ? nc==8 ? s(x,7) : s(x,0) \ + : c==3 ? nc==8 ? s(x,0) : s(x,1) \ + : c==4 ? nc==8 ? s(x,1) : s(x,2) \ + : c==5 ? nc==8 ? s(x,2) : s(x,3) \ + : c==6 ? s(x,3) \ + : s(x,4)) \ + : \ + ( c==0 ? nc==4 ? s(x,1) : nc==8 ? s(x,4) : s(x,3) \ + : c==1 ? nc==4 ? s(x,2) : nc==8 ? s(x,5) : s(x,4) \ + : c==2 ? nc==4 ? s(x,3) : nc==8 ? s(x,6) : s(x,5) \ + : c==3 ? nc==8 ? s(x,7) : s(x,0) \ + : c==4 ? nc==8 ? s(x,0) : s(x,1) \ + : c==5 ? nc==8 ? s(x,1) : s(x,2) \ + : c==6 ? s(x,2) \ + : s(x,3))) + +#if defined(IT4_SET) +#undef dec_imvars +#define dec_imvars +#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c) +#elif defined(IT1_SET) +#undef dec_imvars +#define dec_imvars +#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c) +#else +#define inv_rnd(y,x,k,c) s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]) +#endif + +#if defined(IL4_SET) +#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c) +#elif defined(IL1_SET) +#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c) +#else +#define inv_lrnd(y,x,k,c) s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c] +#endif + +aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) +{ uint32_t locals(b0, b1); + const uint32_t *kp = cx->k_sch + nc * cx->n_rnd; + dec_imvars /* declare variables for inv_mcol() if needed */ + + if(!(cx->n_blk & 2)) return aes_bad; + + state_in(b0, in_blk, kp); + +#if (DEC_UNROLL == FULL) + + kp = cx->k_sch + 9 * nc; + switch(cx->n_rnd) + { + case 14: round(inv_rnd, b1, b0, kp + 4 * nc); + round(inv_rnd, b0, b1, kp + 3 * nc); + case 12: round(inv_rnd, b1, b0, kp + 2 * nc); + round(inv_rnd, b0, b1, kp + nc ); + case 10: round(inv_rnd, b1, b0, kp ); + round(inv_rnd, b0, b1, kp - nc); + round(inv_rnd, b1, b0, kp - 2 * nc); + round(inv_rnd, b0, b1, kp - 3 * nc); + round(inv_rnd, b1, b0, kp - 4 * nc); + round(inv_rnd, b0, b1, kp - 5 * nc); + round(inv_rnd, b1, b0, kp - 6 * nc); + round(inv_rnd, b0, b1, kp - 7 * nc); + round(inv_rnd, b1, b0, kp - 8 * nc); + round(inv_lrnd, b0, b1, kp - 9 * nc); + } +#else + +#if (DEC_UNROLL == PARTIAL) + { uint32_t rnd; + for(rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd) + { + kp -= nc; + round(inv_rnd, b1, b0, kp); + kp -= nc; + round(inv_rnd, b0, b1, kp); + } + kp -= nc; + round(inv_rnd, b1, b0, kp); +#else + { uint32_t rnd, *p0 = b0, *p1 = b1, *pt; + for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd) + { + kp -= nc; + round(inv_rnd, p1, p0, kp); + pt = p0, p0 = p1, p1 = pt; + } +#endif + kp -= nc; + round(inv_lrnd, b0, b1, kp); + } +#endif + + state_out(out_blk, b0); + return aes_good; +} + +#endif diff --git a/src/lib/crypto/builtin/aes/aeskey.c b/src/lib/crypto/builtin/aes/aeskey.c new file mode 100644 index 0000000..60f766b --- /dev/null +++ b/src/lib/crypto/builtin/aes/aeskey.c @@ -0,0 +1,369 @@ +/* + ------------------------------------------------------------------------- + Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explcit or implied warranties + in respect of any properties, including, but not limited to, correctness + and fitness for purpose. + ------------------------------------------------------------------------- + Issue Date: 21/01/2002 + + This file contains the code for implementing the key schedule for AES + (Rijndael) for block and key sizes of 16, 24, and 32 bytes. +*/ + +#include "aesopt.h" + +#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7) +#error An illegal block size has been specified. +#endif + +/* Subroutine to set the block size (if variable) in bytes, legal + values being 16, 24 and 32. +*/ + +#if !defined(BLOCK_SIZE) && defined(SET_BLOCK_LENGTH) + +aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]) +{ +#if !defined(FIXED_TABLES) + if(!tab_init) gen_tabs(); +#endif + + if((blen & 7) || blen < 16 || blen > 32) + { + cx->n_blk = 0; return aes_bad; + } + + cx->n_blk = blen; + return aes_good; +} + +#endif + +/* Initialise the key schedule from the user supplied key. The key + length is now specified in bytes - 16, 24 or 32 as appropriate. + This corresponds to bit lengths of 128, 192 and 256 bits, and + to Nk values of 4, 6 and 8 respectively. + + The following macros implement a single cycle in the key + schedule generation process. The number of cycles needed + for each cx->n_col and nk value is: + + nk = 4 5 6 7 8 + ------------------------------ + cx->n_col = 4 10 9 8 7 7 + cx->n_col = 5 14 11 10 9 9 + cx->n_col = 6 19 15 12 11 11 + cx->n_col = 7 21 19 16 13 14 + cx->n_col = 8 29 23 19 17 14 +*/ + +#if defined(ENCRYPTION_KEY_SCHEDULE) + +#define ke4(k,i) \ +{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \ + k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \ +} +#define kel4(k,i) \ +{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \ + k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \ +} + +#define ke6(k,i) \ +{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \ + k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \ + k[6*(i)+10] = ss[4] ^= ss[3]; k[6*(i)+11] = ss[5] ^= ss[4]; \ +} +#define kel6(k,i) \ +{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \ + k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \ +} + +#define ke8(k,i) \ +{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \ + k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \ + k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); k[8*(i)+13] = ss[5] ^= ss[4]; \ + k[8*(i)+14] = ss[6] ^= ss[5]; k[8*(i)+15] = ss[7] ^= ss[6]; \ +} +#define kel8(k,i) \ +{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \ + k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \ +} + +aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) +{ uint32_t ss[8]; + +#if !defined(FIXED_TABLES) + if(!tab_init) gen_tabs(); +#endif + +#if !defined(BLOCK_SIZE) + if(!cx->n_blk) cx->n_blk = 16; +#else + cx->n_blk = BLOCK_SIZE; +#endif + + cx->n_blk = (cx->n_blk & ~3U) | 1; + + cx->k_sch[0] = ss[0] = word_in(in_key ); + cx->k_sch[1] = ss[1] = word_in(in_key + 4); + cx->k_sch[2] = ss[2] = word_in(in_key + 8); + cx->k_sch[3] = ss[3] = word_in(in_key + 12); + +#if (BLOCK_SIZE == 16) && (ENC_UNROLL != NONE) + + switch(klen) + { + case 16: ke4(cx->k_sch, 0); ke4(cx->k_sch, 1); + ke4(cx->k_sch, 2); ke4(cx->k_sch, 3); + ke4(cx->k_sch, 4); ke4(cx->k_sch, 5); + ke4(cx->k_sch, 6); ke4(cx->k_sch, 7); + ke4(cx->k_sch, 8); kel4(cx->k_sch, 9); + cx->n_rnd = 10; break; + case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + ke6(cx->k_sch, 0); ke6(cx->k_sch, 1); + ke6(cx->k_sch, 2); ke6(cx->k_sch, 3); + ke6(cx->k_sch, 4); ke6(cx->k_sch, 5); + ke6(cx->k_sch, 6); kel6(cx->k_sch, 7); + cx->n_rnd = 12; break; + case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + cx->k_sch[6] = ss[6] = word_in(in_key + 24); + cx->k_sch[7] = ss[7] = word_in(in_key + 28); + ke8(cx->k_sch, 0); ke8(cx->k_sch, 1); + ke8(cx->k_sch, 2); ke8(cx->k_sch, 3); + ke8(cx->k_sch, 4); ke8(cx->k_sch, 5); + kel8(cx->k_sch, 6); + cx->n_rnd = 14; break; + default: cx->n_rnd = 0; return aes_bad; + } +#else + { uint32_t i, l; + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + l = (nc * cx->n_rnd + nc - 1) / (klen >> 2); + + switch(klen) + { + case 16: for(i = 0; i < l; ++i) + ke4(cx->k_sch, i); + break; + case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + for(i = 0; i < l; ++i) + ke6(cx->k_sch, i); + break; + case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + cx->k_sch[6] = ss[6] = word_in(in_key + 24); + cx->k_sch[7] = ss[7] = word_in(in_key + 28); + for(i = 0; i < l; ++i) + ke8(cx->k_sch, i); + break; + default: cx->n_rnd = 0; return aes_bad; + } + } +#endif + + return aes_good; +} + +#endif + +#if defined(DECRYPTION_KEY_SCHEDULE) + +#if (DEC_ROUND != NO_TABLES) +#define d_vars dec_imvars +#define ff(x) inv_mcol(x) +#else +#define ff(x) (x) +#define d_vars +#endif + +#if 1 +#define kdf4(k,i) \ +{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; ss[1] = ss[1] ^ ss[3]; ss[2] = ss[2] ^ ss[3]; ss[3] = ss[3]; \ + ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; \ + ss[4] ^= k[4*(i)]; k[4*(i)+4] = ff(ss[4]); ss[4] ^= k[4*(i)+1]; k[4*(i)+5] = ff(ss[4]); \ + ss[4] ^= k[4*(i)+2]; k[4*(i)+6] = ff(ss[4]); ss[4] ^= k[4*(i)+3]; k[4*(i)+7] = ff(ss[4]); \ +} +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ + k[4*(i)+4] = ss[4] ^= k[4*(i)]; k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \ + k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \ +} +#define kdl4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; \ + k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; k[4*(i)+5] = ss[1] ^ ss[3]; \ + k[4*(i)+6] = ss[0]; k[4*(i)+7] = ss[1]; \ +} +#else +#define kdf4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+ 4] = ff(ss[0]); ss[1] ^= ss[0]; k[4*(i)+ 5] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[4*(i)+ 6] = ff(ss[2]); ss[3] ^= ss[2]; k[4*(i)+ 7] = ff(ss[3]); \ +} +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[3],3) ^ rcon_tab[i]; \ + ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[4*(i)+ 4] = ss[4] ^= k[4*(i)]; \ + ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[4] ^= k[4*(i)+ 1]; \ + ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[4] ^= k[4*(i)+ 2]; \ + ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[4] ^= k[4*(i)+ 3]; \ +} +#define kdl4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+ 4] = ss[0]; ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[1]; \ + ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[2]; ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[3]; \ +} +#endif + +#define kdf6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 6] = ff(ss[0]); ss[1] ^= ss[0]; k[6*(i)+ 7] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[6*(i)+ 8] = ff(ss[2]); ss[3] ^= ss[2]; k[6*(i)+ 9] = ff(ss[3]); \ + ss[4] ^= ss[3]; k[6*(i)+10] = ff(ss[4]); ss[5] ^= ss[4]; k[6*(i)+11] = ff(ss[5]); \ +} +#define kd6(k,i) \ +{ ss[6] = ls_box(ss[5],3) ^ rcon_tab[i]; \ + ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \ + ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \ + ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \ + ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \ + ss[4] ^= ss[3]; k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \ + ss[5] ^= ss[4]; k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \ +} +#define kdl6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 6] = ss[0]; ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[1]; \ + ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[2]; ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[3]; \ +} + +#define kdf8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 8] = ff(ss[0]); ss[1] ^= ss[0]; k[8*(i)+ 9] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[8*(i)+10] = ff(ss[2]); ss[3] ^= ss[2]; k[8*(i)+11] = ff(ss[3]); \ + ss[4] ^= ls_box(ss[3],0); k[8*(i)+12] = ff(ss[4]); ss[5] ^= ss[4]; k[8*(i)+13] = ff(ss[5]); \ + ss[6] ^= ss[5]; k[8*(i)+14] = ff(ss[6]); ss[7] ^= ss[6]; k[8*(i)+15] = ff(ss[7]); \ +} +#define kd8(k,i) \ +{ uint32_t g = ls_box(ss[7],3) ^ rcon_tab[i]; \ + ss[0] ^= g; g = ff(g); k[8*(i)+ 8] = g ^= k[8*(i)]; \ + ss[1] ^= ss[0]; k[8*(i)+ 9] = g ^= k[8*(i)+ 1]; \ + ss[2] ^= ss[1]; k[8*(i)+10] = g ^= k[8*(i)+ 2]; \ + ss[3] ^= ss[2]; k[8*(i)+11] = g ^= k[8*(i)+ 3]; \ + g = ls_box(ss[3],0); \ + ss[4] ^= g; g = ff(g); k[8*(i)+12] = g ^= k[8*(i)+ 4]; \ + ss[5] ^= ss[4]; k[8*(i)+13] = g ^= k[8*(i)+ 5]; \ + ss[6] ^= ss[5]; k[8*(i)+14] = g ^= k[8*(i)+ 6]; \ + ss[7] ^= ss[6]; k[8*(i)+15] = g ^= k[8*(i)+ 7]; \ +} +#define kdl8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 8] = ss[0]; ss[1] ^= ss[0]; k[8*(i)+ 9] = ss[1]; \ + ss[2] ^= ss[1]; k[8*(i)+10] = ss[2]; ss[3] ^= ss[2]; k[8*(i)+11] = ss[3]; \ +} + +aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) +{ uint32_t ss[8]; + d_vars + +#if !defined(FIXED_TABLES) + if(!tab_init) gen_tabs(); +#endif + +#if !defined(BLOCK_SIZE) + if(!cx->n_blk) cx->n_blk = 16; +#else + cx->n_blk = BLOCK_SIZE; +#endif + + cx->n_blk = (cx->n_blk & ~3U) | 2; + + cx->k_sch[0] = ss[0] = word_in(in_key ); + cx->k_sch[1] = ss[1] = word_in(in_key + 4); + cx->k_sch[2] = ss[2] = word_in(in_key + 8); + cx->k_sch[3] = ss[3] = word_in(in_key + 12); + +#if (BLOCK_SIZE == 16) && (DEC_UNROLL != NONE) + + switch(klen) + { + case 16: kdf4(cx->k_sch, 0); kd4(cx->k_sch, 1); + kd4(cx->k_sch, 2); kd4(cx->k_sch, 3); + kd4(cx->k_sch, 4); kd4(cx->k_sch, 5); + kd4(cx->k_sch, 6); kd4(cx->k_sch, 7); + kd4(cx->k_sch, 8); kdl4(cx->k_sch, 9); + cx->n_rnd = 10; break; + case 24: ss[4] = word_in(in_key + 16); + cx->k_sch[4] = ff(ss[4]); + ss[5] = word_in(in_key + 20); + cx->k_sch[5] = ff(ss[5]); + kdf6(cx->k_sch, 0); kd6(cx->k_sch, 1); + kd6(cx->k_sch, 2); kd6(cx->k_sch, 3); + kd6(cx->k_sch, 4); kd6(cx->k_sch, 5); + kd6(cx->k_sch, 6); kdl6(cx->k_sch, 7); + cx->n_rnd = 12; break; + case 32: ss[4] = word_in(in_key + 16); + cx->k_sch[4] = ff(ss[4]); + ss[5] = word_in(in_key + 20); + cx->k_sch[5] = ff(ss[5]); + ss[6] = word_in(in_key + 24); + cx->k_sch[6] = ff(ss[6]); + ss[7] = word_in(in_key + 28); + cx->k_sch[7] = ff(ss[7]); + kdf8(cx->k_sch, 0); kd8(cx->k_sch, 1); + kd8(cx->k_sch, 2); kd8(cx->k_sch, 3); + kd8(cx->k_sch, 4); kd8(cx->k_sch, 5); + kdl8(cx->k_sch, 6); + cx->n_rnd = 14; break; + default: cx->n_rnd = 0; return aes_bad; + } +#else + { uint32_t i, l; + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + l = (nc * cx->n_rnd + nc - 1) / (klen >> 2); + + switch(klen) + { + case 16: + for(i = 0; i < l; ++i) + ke4(cx->k_sch, i); + break; + case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + for(i = 0; i < l; ++i) + ke6(cx->k_sch, i); + break; + case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + cx->k_sch[6] = ss[6] = word_in(in_key + 24); + cx->k_sch[7] = ss[7] = word_in(in_key + 28); + for(i = 0; i < l; ++i) + ke8(cx->k_sch, i); + break; + default: cx->n_rnd = 0; return aes_bad; + } +#if (DEC_ROUND != NO_TABLES) + for(i = nc; i < nc * cx->n_rnd; ++i) + cx->k_sch[i] = inv_mcol(cx->k_sch[i]); +#endif + } +#endif + + return aes_good; +} + +#endif diff --git a/src/lib/crypto/builtin/aes/aeskeypp.c b/src/lib/crypto/builtin/aes/aeskeypp.c new file mode 100644 index 0000000..89fd900 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aeskeypp.c @@ -0,0 +1,399 @@ +/* + ------------------------------------------------------------------------- + Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explcit or implied warranties + in respect of any properties, including, but not limited to, correctness + and fitness for purpose. + ------------------------------------------------------------------------- + Issue Date: 21/01/2002 + + This file contains the code for implementing the key schedule for AES + (Rijndael) for block and key sizes of 16, 20, 24, 28 and 32 bytes. +*/ + +#include "aesopt.h" + +/* Subroutine to set the block size (if variable) in bytes, legal + values being 16, 24 and 32. +*/ + +#if !defined(BLOCK_SIZE) && defined(SET_BLOCK_LENGTH) + +/* Subroutine to set the block size (if variable) in bytes, legal + values being 16, 24 and 32. +*/ + +aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]) +{ +#if !defined(FIXED_TABLES) + if(!tab_init) gen_tabs(); +#endif + + if((blen & 3) || blen < 16 || blen > 32) + { + cx->n_blk = 0; return aes_bad; + } + + cx->n_blk = blen; + return aes_good; +} + +#endif + +/* Initialise the key schedule from the user supplied key. The key + length is now specified in bytes - 16, 24 or 32 as appropriate. + This corresponds to bit lengths of 128, 192 and 256 bits, and + to Nk values of 4, 6 and 8 respectively. + + The following macros implement a single cycle in the key + schedule generation process. The number of cycles needed + for each cx->n_blk and nk value is: + + nk = 4 5 6 7 8 + ------------------------------ + cx->n_blk = 4 10 9 8 7 7 + cx->n_blk = 5 14 11 10 9 9 + cx->n_blk = 6 19 15 12 11 11 + cx->n_blk = 7 21 19 16 13 14 + cx->n_blk = 8 29 23 19 17 14 +*/ + +/* Initialise the key schedule from the user supplied key. The key + length is now specified in bytes - 16, 20, 24, 28 or 32 as + appropriate. This corresponds to bit lengths of 128, 160, 192, + 224 and 256 bits, and to Nk values of 4, 5, 6, 7 & 8 respectively. + */ + +#define mx(t,f) (*t++ = inv_mcol(*f),f++) +#define cp(t,f) *t++ = *f++ + +#if BLOCK_SIZE == 16 +#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s) +#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s) +#elif BLOCK_SIZE == 20 +#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ + cp(d,s) +#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ + mx(d,s) +#elif BLOCK_SIZE == 24 +#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ + cp(d,s); cp(d,s) +#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ + mx(d,s); mx(d,s) +#elif BLOCK_SIZE == 28 +#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ + cp(d,s); cp(d,s); cp(d,s) +#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ + mx(d,s); mx(d,s); mx(d,s) +#elif BLOCK_SIZE == 32 +#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ + cp(d,s); cp(d,s); cp(d,s); cp(d,s) +#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ + mx(d,s); mx(d,s); mx(d,s); mx(d,s) +#else + +#define cpy(d,s) \ +switch(nc) \ +{ case 8: cp(d,s); \ + case 7: cp(d,s); \ + case 6: cp(d,s); \ + case 5: cp(d,s); \ + case 4: cp(d,s); cp(d,s); \ + cp(d,s); cp(d,s); \ +} + +#define mix(d,s) \ +switch(nc) \ +{ case 8: mx(d,s); \ + case 7: mx(d,s); \ + case 6: mx(d,s); \ + case 5: mx(d,s); \ + case 4: mx(d,s); mx(d,s); \ + mx(d,s); mx(d,s); \ +} + +#endif + +/* The following macros implement a single cycle in the key + schedule generation process. The number of cycles needed + for each cx->n_blk and nk value is: + + nk = 4 5 6 7 8 + ----------------------- + cx->n_blk = 4 10 9 8 7 7 + cx->n_blk = 5 14 11 10 9 9 + cx->n_blk = 6 19 15 12 11 11 + cx->n_blk = 7 21 19 16 13 14 + cx->n_blk = 8 29 23 19 17 14 +*/ + +#define ks4(i) \ +{ p ^= ls_box(s,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \ + cx->k_sch[4*(i)+4] = p; \ + cx->k_sch[4*(i)+5] = q; \ + cx->k_sch[4*(i)+6] = r; \ + cx->k_sch[4*(i)+7] = s; \ +} + +#define ks5(i) \ +{ p ^= ls_box(t,3) ^ rcon_tab[i]; q ^= p; \ + r ^= q; s ^= r; t ^= s; \ + cx->k_sch[5*(i)+ 5] = p; \ + cx->k_sch[5*(i)+ 6] = q; \ + cx->k_sch[5*(i)+ 7] = r; \ + cx->k_sch[5*(i)+ 8] = s; \ + cx->k_sch[5*(i)+ 9] = t; \ +} + +#define ks6(i) \ +{ p ^= ls_box(u,3) ^ rcon_tab[i]; q ^= p; \ + r ^= q; s ^= r; t ^= s; u ^= t; \ + cx->k_sch[6*(i)+ 6] = p; \ + cx->k_sch[6*(i)+ 7] = q; \ + cx->k_sch[6*(i)+ 8] = r; \ + cx->k_sch[6*(i)+ 9] = s; \ + cx->k_sch[6*(i)+10] = t; \ + cx->k_sch[6*(i)+11] = u; \ +} + +#define ks7(i) \ +{ p ^= ls_box(v,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \ + t ^= ls_box(s,0); u ^= t; v ^= u; \ + cx->k_sch[7*(i)+ 7] = p; \ + cx->k_sch[7*(i)+ 8] = q; \ + cx->k_sch[7*(i)+ 9] = r; \ + cx->k_sch[7*(i)+10] = s; \ + cx->k_sch[7*(i)+11] = t; \ + cx->k_sch[7*(i)+12] = u; \ + cx->k_sch[7*(i)+13] = v; \ +} + +#define ks8(i) \ +{ p ^= ls_box(w,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \ + t ^= ls_box(s,0); u ^= t; v ^= u; w ^= v; \ + cx->k_sch[8*(i)+ 8] = p; \ + cx->k_sch[8*(i)+ 9] = q; \ + cx->k_sch[8*(i)+10] = r; \ + cx->k_sch[8*(i)+11] = s; \ + cx->k_sch[8*(i)+12] = t; \ + cx->k_sch[8*(i)+13] = u; \ + cx->k_sch[8*(i)+14] = v; \ + cx->k_sch[8*(i)+15] = w; \ +} + +#if defined(ENCRYPTION_KEY_SCHEDULE) + +aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) +{ uint32_t i,p,q,r,s,t,u,v,w; + +#if !defined(FIXED_TABLES) + if(!tab_init) gen_tabs(); +#endif + +#if !defined(BLOCK_SIZE) + if(!cx->n_blk) cx->n_blk = 16; +#else + cx->n_blk = BLOCK_SIZE; +#endif + + cx->n_blk = (cx->n_blk & ~3) | 1; + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + + cx->k_sch[0] = p = word_in(in_key ); + cx->k_sch[1] = q = word_in(in_key + 4); + cx->k_sch[2] = r = word_in(in_key + 8); + cx->k_sch[3] = s = word_in(in_key + 12); + +#if BLOCK_SIZE == 16 && defined(UNROLL) + + switch(klen >> 2) + { + case 4: ks4(0); ks4(1); ks4(2); ks4(3); + ks4(4); ks4(5); ks4(6); ks4(7); + ks4(8); ks4(9); + cx->n_rnd = 10; break; + case 5: cx->k_sch[4] = t = word_in(in_key + 16); + ks5(0); ks5(1); ks5(2); ks5(3); + ks5(4); ks5(5); ks5(6); ks5(7); + ks5(8); + cx->n_rnd = 11; break; + case 6: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + ks6(0); ks6(1); ks6(2); ks6(3); + ks6(4); ks6(5); ks6(6); ks6(7); + cx->n_rnd = 12; break; + case 7: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + ks7(0); ks7(1); ks7(2); ks7(3); + ks7(4); ks7(5); ks7(6); + cx->n_rnd = 13; break; + case 8: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + cx->k_sch[7] = w = word_in(in_key + 28); + ks8(0); ks8(1); ks8(2); ks8(3); + ks8(4); ks8(5); ks8(6); + cx->n_rnd = 14; break; + default:cx->n_rnd = 0; return aes_bad; + } +#else + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + { + uint32_t l = (nc * (cx->n_rnd + 1) - 1) / (klen >> 2); + switch(klen >> 2) + { + case 4: for(i = 0; i < l; ++i) + ks4(i); + break; + case 5: cx->k_sch[4] = t = word_in(in_key + 16); + for(i = 0; i < l; ++i) + ks5(i); + break; + case 6: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + for(i = 0; i < l; ++i) + ks6(i); + break; + case 7: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + for(i = 0; i < l; ++i) + ks7(i); + break; + case 8: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + cx->k_sch[7] = w = word_in(in_key + 28); + for(i = 0; i < l; ++i) + ks8(i); + break; + } + } +#endif + + return aes_good; +} + +#endif + +#if defined(DECRYPTION_KEY_SCHEDULE) + +aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) +{ uint32_t i,p,q,r,s,t,u,v,w; + dec_imvars + +#if !defined(FIXED_TABLES) + if(!tab_init) gen_tabs(); +#endif + +#if !defined(BLOCK_SIZE) + if(!cx->n_blk) cx->n_blk = 16; +#else + cx->n_blk = BLOCK_SIZE; +#endif + + cx->n_blk = (cx->n_blk & ~3) | 2; + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + + cx->k_sch[0] = p = word_in(in_key ); + cx->k_sch[1] = q = word_in(in_key + 4); + cx->k_sch[2] = r = word_in(in_key + 8); + cx->k_sch[3] = s = word_in(in_key + 12); + +#if BLOCK_SIZE == 16 && defined(UNROLL) + + switch(klen >> 2) + { + case 4: ks4(0); ks4(1); ks4(2); ks4(3); + ks4(4); ks4(5); ks4(6); ks4(7); + ks4(8); ks4(9); + cx->n_rnd = 10; break; + case 5: cx->k_sch[4] = t = word_in(in_key + 16); + ks5(0); ks5(1); ks5(2); ks5(3); + ks5(4); ks5(5); ks5(6); ks5(7); + ks5(8); + cx->n_rnd = 11; break; + case 6: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + ks6(0); ks6(1); ks6(2); ks6(3); + ks6(4); ks6(5); ks6(6); ks6(7); + cx->n_rnd = 12; break; + case 7: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + ks7(0); ks7(1); ks7(2); ks7(3); + ks7(4); ks7(5); ks7(6); + cx->n_rnd = 13; break; + case 8: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + cx->k_sch[7] = w = word_in(in_key + 28); + ks8(0); ks8(1); ks8(2); ks8(3); + ks8(4); ks8(5); ks8(6); + cx->n_rnd = 14; break; + default:cx->n_rnd = 0; return aes_bad; + } +#else + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + { + uint32_t l = (nc * (cx->n_rnd + 1) - 1) / (klen >> 2); + switch(klen >> 2) + { + case 4: for(i = 0; i < l; ++i) + ks4(i); + break; + case 5: cx->k_sch[4] = t = word_in(in_key + 16); + for(i = 0; i < l; ++i) + ks5(i); + break; + case 6: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + for(i = 0; i < l; ++i) + ks6(i); + break; + case 7: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + for(i = 0; i < l; ++i) + ks7(i); + break; + case 8: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + cx->k_sch[7] = w = word_in(in_key + 28); + for(i = 0; i < l; ++i) + ks8(i); + break; + } + } +#endif + +#if (DEC_ROUND != NO_TABLES) + for(i = nc; i < nc * cx->n_rnd; ++i) + cx->k_sch[i] = inv_mcol(cx->k_sch[i]); +#endif + + return aes_good; +} + +#endif diff --git a/src/lib/crypto/builtin/aes/aesopt.h b/src/lib/crypto/builtin/aes/aesopt.h new file mode 100644 index 0000000..006fbb3 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aesopt.h @@ -0,0 +1,851 @@ +/* + ------------------------------------------------------------------------- + Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explcit or implied warranties + in respect of any properties, including, but not limited to, correctness + and fitness for purpose. + ------------------------------------------------------------------------- + Issue Date: 07/02/2002 + + This file contains the compilation options for AES (Rijndael) and code + that is common across encryption, key scheduling and table generation. + + + OPERATION + + These source code files implement the AES algorithm Rijndael designed by + Joan Daemen and Vincent Rijmen. The version in aes.c is designed for + block and key sizes of 128, 192 and 256 bits (16, 24 and 32 bytes) while + that in aespp.c provides for block and keys sizes of 128, 160, 192, 224 + and 256 bits (16, 20, 24, 28 and 32 bytes). This file is a common header + file for these two implementations and for aesref.c, which is a reference + implementation. + + This version is designed for flexibility and speed using operations on + 32-bit words rather than operations on bytes. It provides aes_both fixed + and dynamic block and key lengths and can also run with either big or + little endian internal byte order (see aes.h). It inputs block and key + lengths in bytes with the legal values being 16, 24 and 32 for aes.c and + 16, 20, 24, 28 and 32 for aespp.c + + THE CIPHER INTERFACE + + uint8_t (an unsigned 8-bit type) + uint32_t (an unsigned 32-bit type) + aes_fret (a signed 16 bit type for function return values) + aes_good (value != 0, a good return) + aes_bad (value == 0, an error return) + struct aes_ctx (structure for the cipher encryption context) + struct aes_ctx (structure for the cipher decryption context) + aes_rval the function return type (aes_fret if not DLL) + + C subroutine calls: + + aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]); + aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); + aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); + + aes_rval aes_dec_len(unsigned int blen, aes_ctx cx[1]); + aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); + aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); + + IMPORTANT NOTE: If you are using this C interface and your compiler does + not set the memory used for objects to zero before use, you will need to + ensure that cx.s_flg is set to zero before using these subroutine calls. + + C++ aes class subroutines: + + class AESclass for encryption + class AESclass for decryption + + aes_rval len(unsigned int blen = 16); + aes_rval key(const unsigned char in_key[], unsigned int klen); + aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]); + + aes_rval len(unsigned int blen = 16); + aes_rval key(const unsigned char in_key[], unsigned int klen); + aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]); + + The block length inputs to set_block and set_key are in numbers of + BYTES, not bits. The calls to subroutines must be made in the above + order but multiple calls can be made without repeating earlier calls + if their parameters have not changed. If the cipher block length is + variable but set_blk has not been called before cipher operations a + value of 16 is assumed (that is, the AES block size). In contrast to + earlier versions the block and key length parameters are now checked + for correctness and the encryption and decryption routines check to + ensure that an appropriate key has been set before they are called. + + COMPILATION + + The files used to provide AES (Rijndael) are + + a. aes.h for the definitions needed for use in C. + b. aescpp.h for the definitions needed for use in C++. + c. aesopt.h for setting compilation options (also includes common + code). + d. aescrypt.c for encryption and decrytpion, or + e. aescrypt.asm for encryption and decryption using assembler code. + f. aeskey.c for key scheduling. + g. aestab.c for table loading or generation. + h. uitypes.h for defining fixed length unsigned integers. + + The assembler code uses the NASM assembler. The above files provice + block and key lengths of 16, 24 and 32 bytes (128, 192 and 256 bits). + If aescrypp.c and aeskeypp.c are used instead of aescrypt.c and + aeskey.c respectively, the block and key lengths can then be 16, 20, + 24, 28 or 32 bytes. However this code has not been optimised to the + same extent and is hence slower (esepcially for the AES block size + of 16 bytes). + + To compile AES (Rijndael) for use in C code use aes.h and exclude + the AES_DLL define in aes.h + + To compile AES (Rijndael) for use in in C++ code use aescpp.h and + exclude the AES_DLL define in aes.h + + To compile AES (Rijndael) in C as a Dynamic Link Library DLL) use + aes.h, include the AES_DLL define and compile the DLL. If using + the test files to test the DLL, exclude aes.c from the test build + project and compile it with the same defines as used for the DLL + (ensure that the DLL path is correct) + + CONFIGURATION OPTIONS (here and in aes.h) + + a. define BLOCK_SIZE in aes.h to set the cipher block size (16, 24 + or 32 for the standard code, or 16, 20, 24, 28 or 32 for the + extended code) or leave this undefined for dynamically variable + block size (this will result in much slower code). + b. set AES_DLL in aes.h if AES (Rijndael) is to be compiled as a DLL + c. You may need to set PLATFORM_BYTE_ORDER to define the byte order. + d. If you want the code to run in a specific internal byte order, then + INTERNAL_BYTE_ORDER must be set accordingly. + e. set other configuration options decribed below. +*/ + +#ifndef _AESOPT_H +#define _AESOPT_H + +/* START OF CONFIGURATION OPTIONS + + USE OF DEFINES + + Later in this section there are a number of defines that control + the operation of the code. In each section, the purpose of each + define is explained so that the relevant form can be included or + excluded by setting either 1's or 0's respectively on the branches + of the related #if clauses. +*/ + +#include "autoconf.h" + +/* 1. PLATFORM SPECIFIC INCLUDES */ + +#if /* defined(__GNUC__) || */ defined(__GNU_LIBRARY__) +# include <endian.h> +# include <byteswap.h> +#elif defined(__CRYPTLIB__) +# if defined( INC_ALL ) +# include "crypt.h" +# elif defined( INC_CHILD ) +# include "../crypt.h" +# else +# include "crypt.h" +# endif +# if defined(DATA_LITTLEENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# else +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +#elif defined(_MSC_VER) +# include <stdlib.h> +#elif defined(__m68k__) && defined(__palmos__) +# include <FloatMgr.h> /* defines BIG_ENDIAN */ +#elif defined(_MIPSEB) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +#elif defined(_MIPSEL) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +#elif defined(_WIN32) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +#elif !defined(_WIN32) +# include <stdlib.h> +# if defined(HAVE_ENDIAN_H) +# include <endian.h> +# elif defined(HAVE_MACHINE_ENDIAN_H) +# include <machine/endian.h> +# else +# include <sys/param.h> +# endif +#endif + +/* 2. BYTE ORDER IN 32-BIT WORDS + + To obtain the highest speed on processors with 32-bit words, this code + needs to determine the order in which bytes are packed into such words. + The following block of code is an attempt to capture the most obvious + ways in which various environemnts specify heir endian definitions. It + may well fail, in which case the definitions will need to be set by + editing at the points marked **** EDIT HERE IF NECESSARY **** below. +*/ +#define AES_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ +#define AES_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ + +#if !defined(PLATFORM_BYTE_ORDER) +#if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN) +# if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# if defined(BYTE_ORDER) +# if (BYTE_ORDER == LITTLE_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif (BYTE_ORDER == BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +# endif +# elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +#elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN) +# if defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +# if defined(_BYTE_ORDER) +# if (_BYTE_ORDER == _LITTLE_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif (_BYTE_ORDER == _BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +# endif +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +#define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +#define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +#elif 1 +#define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +#define UNKNOWN_BYTE_ORDER /* we're guessing */ +#endif +#endif + +/* 3. ASSEMBLER SUPPORT + + If the assembler code is used for encryption and decryption this file only + provides key scheduling so the following defines are used +*/ +#ifdef AES_ASM +#define ENCRYPTION_KEY_SCHEDULE +#define DECRYPTION_KEY_SCHEDULE +#endif + +/* 4. FUNCTIONS REQUIRED + + This implementation provides five main subroutines which provide for + setting block length, setting encryption and decryption keys and for + encryption and decryption. When the assembler code is not being used + the following definition blocks allow the selection of the routines + that are to be included in the compilation. +*/ +#if 1 +#ifndef AES_ASM +#define SET_BLOCK_LENGTH +#endif +#endif + +#if 1 +#ifndef AES_ASM +#define ENCRYPTION_KEY_SCHEDULE +#endif +#endif + +#if 1 +#ifndef AES_ASM +#define DECRYPTION_KEY_SCHEDULE +#endif +#endif + +#if 1 +#ifndef AES_ASM +#define ENCRYPTION +#endif +#endif + +#if 1 +#ifndef AES_ASM +#define DECRYPTION +#endif +#endif + +/* 5. BYTE ORDER WITHIN 32 BIT WORDS + + The fundamental data processing units in Rijndael are 8-bit bytes. The + input, output and key input are all enumerated arrays of bytes in which + bytes are numbered starting at zero and increasing to one less than the + number of bytes in the array in question. This enumeration is only used + for naming bytes and does not imply any adjacency or order relationship + from one byte to another. When these inputs and outputs are considered + as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to + byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. + In this implementation bits are numbered from 0 to 7 starting at the + numerically least significant end of each byte (bit n represents 2^n). + + However, Rijndael can be implemented more efficiently using 32-bit + words by packing bytes into words so that bytes 4*n to 4*n+3 are placed + into word[n]. While in principle these bytes can be assembled into words + in any positions, this implementation only supports the two formats in + which bytes in adjacent positions within words also have adjacent byte + numbers. This order is called big-endian if the lowest numbered bytes + in words have the highest numeric significance and little-endian if the + opposite applies. + + This code can work in either order irrespective of the order used by the + machine on which it runs. Normally the internal byte order will be set + to the order of the processor on which the code is to be run but this + define can be used to reverse this in special situations +*/ +#if 1 +#define INTERNAL_BYTE_ORDER PLATFORM_BYTE_ORDER +#elif defined(AES_LITTLE_ENDIAN) +#define INTERNAL_BYTE_ORDER AES_LITTLE_ENDIAN +#elif defined(AES_BIG_ENDIAN) +#define INTERNAL_BYTE_ORDER AES_BIG_ENDIAN +#endif + +/* 6. FAST INPUT/OUTPUT OPERATIONS. + + On some machines it is possible to improve speed by transferring the + bytes in the input and output arrays to and from the internal 32-bit + variables by addressing these arrays as if they are arrays of 32-bit + words. On some machines this will always be possible but there may + be a large performance penalty if the byte arrays are not aligned on + the normal word boundaries. On other machines this technique will + lead to memory access errors when such 32-bit word accesses are not + properly aligned. The option SAFE_IO avoids such problems but will + often be slower on those machines that support misaligned access + (especially so if care is taken to align the input and output byte + arrays on 32-bit word boundaries). If SAFE_IO is not defined it is + assumed that access to byte arrays as if they are arrays of 32-bit + words will not cause problems when such accesses are misaligned. +*/ +#if 1 +#define SAFE_IO +#endif + +/* + * If PLATFORM_BYTE_ORDER does not match the actual machine byte + * order, the fast word-access code will cause incorrect results. + * Therefore, SAFE_IO is required when the byte order is unknown. + */ +#if !defined(SAFE_IO) && defined(UNKNOWN_BYTE_ORDER) +# error "SAFE_IO must be defined if machine byte order is unknown." +#endif + +/* 7. LOOP UNROLLING + + The code for encryption and decrytpion cycles through a number of rounds + that can be implemented either in a loop or by expanding the code into a + long sequence of instructions, the latter producing a larger program but + one that will often be much faster. The latter is called loop unrolling. + There are also potential speed advantages in expanding two iterations in + a loop with half the number of iterations, which is called partial loop + unrolling. The following options allow partial or full loop unrolling + to be set independently for encryption and decryption +*/ +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) +#define ENC_UNROLL FULL +#elif 0 +#define ENC_UNROLL PARTIAL +#else +#define ENC_UNROLL NONE +#endif + +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) +#define DEC_UNROLL FULL +#elif 0 +#define DEC_UNROLL PARTIAL +#else +#define DEC_UNROLL NONE +#endif + +/* 8. FIXED OR DYNAMIC TABLES + + When this section is included the tables used by the code are compiled + statically into the binary file. Otherwise they are computed once when + the code is first used. +*/ +#if 1 +#define FIXED_TABLES +#endif + +/* 9. FAST FINITE FIELD OPERATIONS + + If this section is included, tables are used to provide faster finite + field arithmetic (this has no effect if FIXED_TABLES is defined). +*/ +#if 1 +#define FF_TABLES +#endif + +/* 10. INTERNAL STATE VARIABLE FORMAT + + The internal state of Rijndael is stored in a number of local 32-bit + word varaibles which can be defined either as an array or as individual + names variables. Include this section if you want to store these local + varaibles in arrays. Otherwise individual local variables will be used. +*/ +#if 1 +#define ARRAYS +#endif + +/* In this implementation the columns of the state array are each held in + 32-bit words. The state array can be held in various ways: in an array + of words, in a number of individual word variables or in a number of + processor registers. The following define maps a variable name x and + a column number c to the way the state array variable is to be held. + The first define below maps the state into an array x[c] whereas the + second form maps the state into a number of individual variables x0, + x1, etc. Another form could map individual state colums to machine + register names. +*/ + +#if defined(ARRAYS) +#define s(x,c) x[c] +#else +#define s(x,c) x##c +#endif + +/* 11. VARIABLE BLOCK SIZE SPEED + + This section is only relevant if you wish to use the variable block + length feature of the code. Include this section if you place more + emphasis on speed rather than code size. +*/ +#if 1 +#define FAST_VARIABLE +#endif + +/* 12. INTERNAL TABLE CONFIGURATION + + This cipher proceeds by repeating in a number of cycles known as 'rounds' + which are implemented by a round function which can optionally be speeded + up using tables. The basic tables are each 256 32-bit words, with either + one or four tables being required for each round function depending on + how much speed is required. The encryption and decryption round functions + are different and the last encryption and decrytpion round functions are + different again making four different round functions in all. + + This means that: + 1. Normal encryption and decryption rounds can each use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + 2. The last encryption and decryption rounds can also use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + + Include or exclude the appropriate definitions below to set the number + of tables used by this implementation. +*/ + +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the normal encryption round */ +#define ENC_ROUND FOUR_TABLES +#elif 0 +#define ENC_ROUND ONE_TABLE +#else +#define ENC_ROUND NO_TABLES +#endif + +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the last encryption round */ +#define LAST_ENC_ROUND FOUR_TABLES +#elif 0 +#define LAST_ENC_ROUND ONE_TABLE +#else +#define LAST_ENC_ROUND NO_TABLES +#endif + +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the normal decryption round */ +#define DEC_ROUND FOUR_TABLES +#elif 0 +#define DEC_ROUND ONE_TABLE +#else +#define DEC_ROUND NO_TABLES +#endif + +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the last decryption round */ +#define LAST_DEC_ROUND FOUR_TABLES +#elif 0 +#define LAST_DEC_ROUND ONE_TABLE +#else +#define LAST_DEC_ROUND NO_TABLES +#endif + +/* The decryption key schedule can be speeded up with tables in the same + way that the round functions can. Include or exclude the following + defines to set this requirement. +*/ +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) +#define KEY_SCHED FOUR_TABLES +#elif 0 +#define KEY_SCHED ONE_TABLE +#else +#define KEY_SCHED NO_TABLES +#endif + +/* END OF CONFIGURATION OPTIONS */ + +#define NO_TABLES 0 /* DO NOT CHANGE */ +#define ONE_TABLE 1 /* DO NOT CHANGE */ +#define FOUR_TABLES 4 /* DO NOT CHANGE */ +#define NONE 0 /* DO NOT CHANGE */ +#define PARTIAL 1 /* DO NOT CHANGE */ +#define FULL 2 /* DO NOT CHANGE */ + +#if defined(BLOCK_SIZE) && ((BLOCK_SIZE & 3) || BLOCK_SIZE < 16 || BLOCK_SIZE > 32) +#error An illegal block size has been specified. +#endif + +#if !defined(BLOCK_SIZE) +#define RC_LENGTH 29 +#else +#define RC_LENGTH 5 * BLOCK_SIZE / 4 - (BLOCK_SIZE == 16 ? 10 : 11) +#endif + +/* Disable at least some poor combinations of options */ + +#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES +#undef LAST_ENC_ROUND +#define LAST_ENC_ROUND NO_TABLES +#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES +#undef LAST_ENC_ROUND +#define LAST_ENC_ROUND ONE_TABLE +#endif + +#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE +#undef ENC_UNROLL +#define ENC_UNROLL NONE +#endif + +#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES +#undef LAST_DEC_ROUND +#define LAST_DEC_ROUND NO_TABLES +#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES +#undef LAST_DEC_ROUND +#define LAST_DEC_ROUND ONE_TABLE +#endif + +#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE +#undef DEC_UNROLL +#define DEC_UNROLL NONE +#endif + +#include "aes.h" + + /* + upr(x,n): rotates bytes within words by n positions, moving bytes to + higher index positions with wrap around into low positions + ups(x,n): moves bytes by n positions to higher index positions in + words but without wrap around + bval(x,n): extracts a byte from a word + */ + +#if (INTERNAL_BYTE_ORDER == AES_LITTLE_ENDIAN) +#if defined(_MSC_VER) +#define upr(x,n) _lrotl((x), 8 * (n)) +#else +#define upr(x,n) (((x) << (8 * (n))) | ((x) >> (32 - 8 * (n)))) +#endif +#define ups(x,n) ((x) << (8 * (n))) +#define bval(x,n) ((uint8_t)((x) >> (8 * (n)))) +#define bytes2word(b0, b1, b2, b3) \ + (((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0)) +#endif + +#if (INTERNAL_BYTE_ORDER == AES_BIG_ENDIAN) +#define upr(x,n) (((x) >> (8 * (n))) | ((x) << (32 - 8 * (n)))) +#define ups(x,n) ((x) >> (8 * (n)))) +#define bval(x,n) ((uint8_t)((x) >> (24 - 8 * (n)))) +#define bytes2word(b0, b1, b2, b3) \ + (((uint32_t)(b0) << 24) | ((uint32_t)(b1) << 16) | ((uint32_t)(b2) << 8) | (b3)) +#endif + +#if defined(SAFE_IO) + +#define word_in(x) bytes2word((x)[0], (x)[1], (x)[2], (x)[3]) +#define word_out(x,v) { (x)[0] = bval(v,0); (x)[1] = bval(v,1); \ + (x)[2] = bval(v,2); (x)[3] = bval(v,3); } + +#elif (INTERNAL_BYTE_ORDER == PLATFORM_BYTE_ORDER) + +#define word_in(x) *(uint32_t*)(x) +#define word_out(x,v) *(uint32_t*)(x) = (v) + +#else + +#if !defined(bswap_32) +#if !defined(_MSC_VER) +#define _lrotl(x,n) (((x) << n) | ((x) >> (32 - n))) +#endif +#define bswap_32(x) ((_lrotl((x),8) & 0x00ff00ff) | (_lrotl((x),24) & 0xff00ff00)) +#endif + +#define word_in(x) bswap_32(*(uint32_t*)(x)) +#define word_out(x,v) *(uint32_t*)(x) = bswap_32(v) + +#endif + +/* the finite field modular polynomial and elements */ + +#define WPOLY 0x011b +#define BPOLY 0x1b + +/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + +#define m1 0x80808080 +#define m2 0x7f7f7f7f +#define FFmulX(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY)) + +/* The following defines provide alternative definitions of FFmulX that might + give improved performance if a fast 32-bit multiply is not available. Note + that a temporary variable u needs to be defined where FFmulX is used. + +#define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) +#define m4 (0x01010101 * BPOLY) +#define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) +*/ + +/* Work out which tables are needed for the different options */ + +#ifdef AES_ASM +#ifdef ENC_ROUND +#undef ENC_ROUND +#endif +#define ENC_ROUND FOUR_TABLES +#ifdef LAST_ENC_ROUND +#undef LAST_ENC_ROUND +#endif +#define LAST_ENC_ROUND FOUR_TABLES +#ifdef DEC_ROUND +#undef DEC_ROUND +#endif +#define DEC_ROUND FOUR_TABLES +#ifdef LAST_DEC_ROUND +#undef LAST_DEC_ROUND +#endif +#define LAST_DEC_ROUND FOUR_TABLES +#ifdef KEY_SCHED +#undef KEY_SCHED +#define KEY_SCHED FOUR_TABLES +#endif +#endif + +#if defined(ENCRYPTION) || defined(AES_ASM) +#if ENC_ROUND == ONE_TABLE +#define FT1_SET +#elif ENC_ROUND == FOUR_TABLES +#define FT4_SET +#else +#define SBX_SET +#endif +#if LAST_ENC_ROUND == ONE_TABLE +#define FL1_SET +#elif LAST_ENC_ROUND == FOUR_TABLES +#define FL4_SET +#elif !defined(SBX_SET) +#define SBX_SET +#endif +#endif + +#if defined(DECRYPTION) || defined(AES_ASM) +#if DEC_ROUND == ONE_TABLE +#define IT1_SET +#elif DEC_ROUND == FOUR_TABLES +#define IT4_SET +#else +#define ISB_SET +#endif +#if LAST_DEC_ROUND == ONE_TABLE +#define IL1_SET +#elif LAST_DEC_ROUND == FOUR_TABLES +#define IL4_SET +#elif !defined(ISB_SET) +#define ISB_SET +#endif +#endif + +#if defined(ENCRYPTION_KEY_SCHEDULE) || defined(DECRYPTION_KEY_SCHEDULE) +#if KEY_SCHED == ONE_TABLE +#define LS1_SET +#define IM1_SET +#elif KEY_SCHED == FOUR_TABLES +#define LS4_SET +#define IM4_SET +#elif !defined(SBX_SET) +#define SBX_SET +#endif +#endif + +#ifdef FIXED_TABLES +#define prefx extern const +#else +#define prefx extern +extern uint8_t tab_init; +void gen_tabs(void); +#endif + +prefx uint32_t rcon_tab[29]; + +#ifdef SBX_SET +prefx uint8_t s_box[256]; +#endif + +#ifdef ISB_SET +prefx uint8_t inv_s_box[256]; +#endif + +#ifdef FT1_SET +prefx uint32_t ft_tab[256]; +#endif + +#ifdef FT4_SET +prefx uint32_t ft_tab[4][256]; +#endif + +#ifdef FL1_SET +prefx uint32_t fl_tab[256]; +#endif + +#ifdef FL4_SET +prefx uint32_t fl_tab[4][256]; +#endif + +#ifdef IT1_SET +prefx uint32_t it_tab[256]; +#endif + +#ifdef IT4_SET +prefx uint32_t it_tab[4][256]; +#endif + +#ifdef IL1_SET +prefx uint32_t il_tab[256]; +#endif + +#ifdef IL4_SET +prefx uint32_t il_tab[4][256]; +#endif + +#ifdef LS1_SET +#ifdef FL1_SET +#undef LS1_SET +#else +prefx uint32_t ls_tab[256]; +#endif +#endif + +#ifdef LS4_SET +#ifdef FL4_SET +#undef LS4_SET +#else +prefx uint32_t ls_tab[4][256]; +#endif +#endif + +#ifdef IM1_SET +prefx uint32_t im_tab[256]; +#endif + +#ifdef IM4_SET +prefx uint32_t im_tab[4][256]; +#endif + +/* Set the number of columns in nc. Note that it is important */ +/* that nc is a constant which is known at compile time if the */ +/* highest speed version of the code is needed */ + +#if defined(BLOCK_SIZE) +#define nc (BLOCK_SIZE >> 2) +#else +#define nc (cx->n_blk >> 2) +#endif + +/* generic definitions of Rijndael macros that use of tables */ + +#define no_table(x,box,vf,rf,c) bytes2word( \ + box[bval(vf(x,0,c),rf(0,c))], \ + box[bval(vf(x,1,c),rf(1,c))], \ + box[bval(vf(x,2,c),rf(2,c))], \ + box[bval(vf(x,3,c),rf(3,c))]) + +#define one_table(x,op,tab,vf,rf,c) \ + ( tab[bval(vf(x,0,c),rf(0,c))] \ + ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ + ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ + ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) + +#define four_tables(x,tab,vf,rf,c) \ + ( tab[0][bval(vf(x,0,c),rf(0,c))] \ + ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ + ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ + ^ tab[3][bval(vf(x,3,c),rf(3,c))]) + +#define vf1(x,r,c) (x) +#define rf1(r,c) (r) +#define rf2(r,c) ((r-c)&3) + +/* perform forward and inverse column mix operation on four bytes in long word x in */ +/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ + +#define dec_fmvars +#if defined(FM4_SET) /* not currently used */ +#define fwd_mcol(x) four_tables(x,fm_tab,vf1,rf1,0) +#elif defined(FM1_SET) /* not currently used */ +#define fwd_mcol(x) one_table(x,upr,fm_tab,vf1,rf1,0) +#else +#undef dec_fmvars +#define dec_fmvars uint32_t f1, f2; +#define fwd_mcol(x) (f1 = (x), f2 = FFmulX(f1), f2 ^ upr(f1 ^ f2, 3) ^ upr(f1, 2) ^ upr(f1, 1)) +#endif + +#define dec_imvars +#if defined(IM4_SET) +#define inv_mcol(x) four_tables(x,im_tab,vf1,rf1,0) +#elif defined(IM1_SET) +#define inv_mcol(x) one_table(x,upr,im_tab,vf1,rf1,0) +#else +#undef dec_imvars +#define dec_imvars uint32_t f2, f4, f8, f9; +#define inv_mcol(x) \ + (f9 = (x), f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \ + f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1)) +#endif + +#if defined(FL4_SET) +#define ls_box(x,c) four_tables(x,fl_tab,vf1,rf2,c) +#elif defined(LS4_SET) +#define ls_box(x,c) four_tables(x,ls_tab,vf1,rf2,c) +#elif defined(FL1_SET) +#define ls_box(x,c) one_table(x,upr,fl_tab,vf1,rf2,c) +#elif defined(LS1_SET) +#define ls_box(x,c) one_table(x,upr,ls_tab,vf1,rf2,c) +#else +#define ls_box(x,c) no_table(x,s_box,vf1,rf2,c) +#endif + +#endif diff --git a/src/lib/crypto/builtin/aes/aessrc.url b/src/lib/crypto/builtin/aes/aessrc.url new file mode 100644 index 0000000..0758737 --- /dev/null +++ b/src/lib/crypto/builtin/aes/aessrc.url @@ -0,0 +1 @@ +http://fp.gladman.plus.com/cryptography_technology/rijndael/index.htm diff --git a/src/lib/crypto/builtin/aes/aestab.c b/src/lib/crypto/builtin/aes/aestab.c new file mode 100644 index 0000000..7a5d69f --- /dev/null +++ b/src/lib/crypto/builtin/aes/aestab.c @@ -0,0 +1,494 @@ +/* + ------------------------------------------------------------------------- + Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explcit or implied warranties + in respect of any properties, including, but not limited to, correctness + and fitness for purpose. + ------------------------------------------------------------------------- + Issue Date: 07/02/2002 +*/ + +#include "aesopt.h" + +#if defined(FIXED_TABLES) || !defined(FF_TABLES) + +/* finite field arithmetic operations */ + +#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) +#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) +#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ + ^ (((x>>5) & 4) * WPOLY)) +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +#endif + +#if defined(FIXED_TABLES) + +#define sb_data(w) \ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) + +#define isb_data(w) \ + w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ + w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ + w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ + w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ + w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ + w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ + w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ + w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ + w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ + w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ + w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ + w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ + w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ + w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ + w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ + w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ + w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ + w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ + w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ + w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ + w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ + w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ + w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ + w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ + w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ + w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ + w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ + w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ + w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ + w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ + w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ + w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d), + +#define mm_data(w) \ + w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ + w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ + w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ + w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ + w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ + w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ + w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ + w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ + w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ + w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ + w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ + w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ + w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ + w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ + w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ + w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ + w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ + w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ + w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ + w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ + w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ + w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ + w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ + w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ + w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ + w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ + w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ + w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ + w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ + w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ + w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ + w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) + +#define h0(x) (x) + +/* These defines are used to ensure tables are generated in the + right format depending on the internal byte order required +*/ + +#define w0(p) bytes2word(p, 0, 0, 0) +#define w1(p) bytes2word(0, p, 0, 0) +#define w2(p) bytes2word(0, 0, p, 0) +#define w3(p) bytes2word(0, 0, 0, p) + +/* Number of elements required in this table for different + block and key lengths is: + + Rcon Table key length (bytes) + Length 16 20 24 28 32 + --------------------- + block 16 | 10 9 8 7 7 + length 20 | 14 11 10 9 9 + (bytes) 24 | 19 15 12 11 11 + 28 | 24 19 16 13 13 + 32 | 29 23 19 17 14 + + this table can be a table of bytes if the key schedule + code is adjusted accordingly +*/ + +#define u0(p) bytes2word(f2(p), p, p, f3(p)) +#define u1(p) bytes2word(f3(p), f2(p), p, p) +#define u2(p) bytes2word(p, f3(p), f2(p), p) +#define u3(p) bytes2word(p, p, f3(p), f2(p)) + +#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) +#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) +#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) +#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) + +const uint32_t rcon_tab[29] = +{ + w0(0x01), w0(0x02), w0(0x04), w0(0x08), + w0(0x10), w0(0x20), w0(0x40), w0(0x80), + w0(0x1b), w0(0x36), w0(0x6c), w0(0xd8), + w0(0xab), w0(0x4d), w0(0x9a), w0(0x2f), + w0(0x5e), w0(0xbc), w0(0x63), w0(0xc6), + w0(0x97), w0(0x35), w0(0x6a), w0(0xd4), + w0(0xb3), w0(0x7d), w0(0xfa), w0(0xef), + w0(0xc5) +}; + +#ifdef SBX_SET +const uint8_t s_box[256] = { sb_data(h0) }; +#endif +#ifdef ISB_SET +const uint8_t inv_s_box[256] = { isb_data(h0) }; +#endif + +#ifdef FT1_SET +const uint32_t ft_tab[256] = { sb_data(u0) }; +#endif +#ifdef FT4_SET +const uint32_t ft_tab[4][256] = + { { sb_data(u0) }, { sb_data(u1) }, { sb_data(u2) }, { sb_data(u3) } }; +#endif + +#ifdef FL1_SET +const uint32_t fl_tab[256] = { sb_data(w0) }; +#endif +#ifdef FL4_SET +const uint32_t fl_tab[4][256] = + { { sb_data(w0) }, { sb_data(w1) }, { sb_data(w2) }, { sb_data(w3) } }; +#endif + +#ifdef IT1_SET +const uint32_t it_tab[256] = { isb_data(v0) }; +#endif +#ifdef IT4_SET +const uint32_t it_tab[4][256] = + { { isb_data(v0) }, { isb_data(v1) }, { isb_data(v2) }, { isb_data(v3) } }; +#endif + +#ifdef IL1_SET +const uint32_t il_tab[256] = { isb_data(w0) }; +#endif +#ifdef IL4_SET +const uint32_t il_tab[4][256] = + { { isb_data(w0) }, { isb_data(w1) }, { isb_data(w2) }, { isb_data(w3) } }; +#endif + +#ifdef LS1_SET +const uint32_t ls_tab[256] = { sb_data(w0) }; +#endif +#ifdef LS4_SET +const uint32_t ls_tab[4][256] = + { { sb_data(w0) }, { sb_data(w1) }, { sb_data(w2) }, { sb_data(w3) } }; +#endif + +#ifdef IM1_SET +const uint32_t im_tab[256] = { mm_data(v0) }; +#endif +#ifdef IM4_SET +const uint32_t im_tab[4][256] = + { { mm_data(v0) }, { mm_data(v1) }, { mm_data(v2) }, { mm_data(v3) } }; +#endif + +#else /* dynamic table generation */ + +uint8_t tab_init = 0; + +#define const + +uint32_t rcon_tab[RC_LENGTH]; + +#ifdef SBX_SET +uint8_t s_box[256]; +#endif +#ifdef ISB_SET +uint8_t inv_s_box[256]; +#endif + +#ifdef FT1_SET +uint32_t ft_tab[256]; +#endif +#ifdef FT4_SET +uint32_t ft_tab[4][256]; +#endif + +#ifdef FL1_SET +uint32_t fl_tab[256]; +#endif +#ifdef FL4_SET +uint32_t fl_tab[4][256]; +#endif + +#ifdef IT1_SET +uint32_t it_tab[256]; +#endif +#ifdef IT4_SET +uint32_t it_tab[4][256]; +#endif + +#ifdef IL1_SET +uint32_t il_tab[256]; +#endif +#ifdef IL4_SET +uint32_t il_tab[4][256]; +#endif + +#ifdef LS1_SET +uint32_t ls_tab[256]; +#endif +#ifdef LS4_SET +uint32_t ls_tab[4][256]; +#endif + +#ifdef IM1_SET +uint32_t im_tab[256]; +#endif +#ifdef IM4_SET +uint32_t im_tab[4][256]; +#endif + +#if !defined(FF_TABLES) + +/* Generate the tables for the dynamic table option + + It will generally be sensible to use tables to compute finite + field multiplies and inverses but where memory is scarse this + code might sometimes be better. But it only has effect during + initialisation so its pretty unimportant in overall terms. +*/ + +/* return 2 ^ (n - 1) where n is the bit number of the highest bit + set in x with x in the range 1 < x < 0x00000200. This form is + used so that locals within fi can be bytes rather than words +*/ + +static uint8_t hibit(const uint32_t x) +{ uint8_t r = (uint8_t)((x >> 1) | (x >> 2)); + + r |= (r >> 2); + r |= (r >> 4); + return (r + 1) >> 1; +} + +/* return the inverse of the finite field element x */ + +static uint8_t fi(const uint8_t x) +{ uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; + + if(x < 2) return x; + + for(;;) + { + if(!n1) return v1; + + while(n2 >= n1) + { + n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); + } + + if(!n2) return v2; + + while(n1 >= n2) + { + n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); + } + } +} + +#else + +/* define the finite field multiplies required for Rijndael */ + +#define f2(x) ((x) ? pow[log[x] + 0x19] : 0) +#define f3(x) ((x) ? pow[log[x] + 0x01] : 0) +#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) +#define fb(x) ((x) ? pow[log[x] + 0x68] : 0) +#define fd(x) ((x) ? pow[log[x] + 0xee] : 0) +#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) +#define fi(x) ((x) ? pow[255 - log[x]]: 0) + +#endif + +/* The forward and inverse affine transformations used in the S-box */ + +#define fwd_affine(x) \ + (w = (uint32_t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(uint8_t)(w^(w>>8))) + +#define inv_affine(x) \ + (w = (uint32_t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(uint8_t)(w^(w>>8))) + +void gen_tabs(void) +{ uint32_t i, w; + +#if defined(FF_TABLES) + + uint8_t pow[512], log[256]; + + /* log and power tables for GF(2^8) finite field with + WPOLY as modular polynomial - the simplest primitive + root is 0x03, used here to generate the tables + */ + + i = 0; w = 1; + do + { + pow[i] = (uint8_t)w; + pow[i + 255] = (uint8_t)w; + log[w] = (uint8_t)i++; + w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); + } + while (w != 1); + +#endif + + for(i = 0, w = 1; i < RC_LENGTH; ++i) + { + rcon_tab[i] = bytes2word(w, 0, 0, 0); + w = f2(w); + } + + for(i = 0; i < 256; ++i) + { uint8_t b; + + b = fwd_affine(fi((uint8_t)i)); + w = bytes2word(f2(b), b, b, f3(b)); + +#ifdef SBX_SET + s_box[i] = b; +#endif + +#ifdef FT1_SET /* tables for a normal encryption round */ + ft_tab[i] = w; +#endif +#ifdef FT4_SET + ft_tab[0][i] = w; + ft_tab[1][i] = upr(w,1); + ft_tab[2][i] = upr(w,2); + ft_tab[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); + +#ifdef FL1_SET /* tables for last encryption round (may also */ + fl_tab[i] = w; /* be used in the key schedule) */ +#endif +#ifdef FL4_SET + fl_tab[0][i] = w; + fl_tab[1][i] = upr(w,1); + fl_tab[2][i] = upr(w,2); + fl_tab[3][i] = upr(w,3); +#endif + +#ifdef LS1_SET /* table for key schedule if fl_tab above is */ + ls_tab[i] = w; /* not of the required form */ +#endif +#ifdef LS4_SET + ls_tab[0][i] = w; + ls_tab[1][i] = upr(w,1); + ls_tab[2][i] = upr(w,2); + ls_tab[3][i] = upr(w,3); +#endif + + b = fi(inv_affine((uint8_t)i)); + w = bytes2word(fe(b), f9(b), fd(b), fb(b)); + +#ifdef IM1_SET /* tables for the inverse mix column operation */ + im_tab[b] = w; +#endif +#ifdef IM4_SET + im_tab[0][b] = w; + im_tab[1][b] = upr(w,1); + im_tab[2][b] = upr(w,2); + im_tab[3][b] = upr(w,3); +#endif + +#ifdef ISB_SET + inv_s_box[i] = b; +#endif +#ifdef IT1_SET /* tables for a normal decryption round */ + it_tab[i] = w; +#endif +#ifdef IT4_SET + it_tab[0][i] = w; + it_tab[1][i] = upr(w,1); + it_tab[2][i] = upr(w,2); + it_tab[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); +#ifdef IL1_SET /* tables for last decryption round */ + il_tab[i] = w; +#endif +#ifdef IL4_SET + il_tab[0][i] = w; + il_tab[1][i] = upr(w,1); + il_tab[2][i] = upr(w,2); + il_tab[3][i] = upr(w,3); +#endif + } + + tab_init = 1; +} + +#endif diff --git a/src/lib/crypto/builtin/aes/deps b/src/lib/crypto/builtin/aes/deps new file mode 100644 index 0000000..08ce3fa --- /dev/null +++ b/src/lib/crypto/builtin/aes/deps @@ -0,0 +1,21 @@ +# +# Generated makefile dependencies follow. +# +aescrypt.so aescrypt.po $(OUTPRE)aescrypt.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h aes.h aescrypt.c aesopt.h \ + uitypes.h +aestab.so aestab.po $(OUTPRE)aestab.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + aes.h aesopt.h aestab.c uitypes.h +aeskey.so aeskey.po $(OUTPRE)aeskey.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + aes.h aeskey.c aesopt.h uitypes.h +aes_s2k.so aes_s2k.po $(OUTPRE)aes_s2k.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h $(srcdir)/../../krb/dk/dk.h \ + aes_s2k.c aes_s2k.h diff --git a/src/lib/crypto/builtin/aes/uitypes.h b/src/lib/crypto/builtin/aes/uitypes.h new file mode 100644 index 0000000..3a72921 --- /dev/null +++ b/src/lib/crypto/builtin/aes/uitypes.h @@ -0,0 +1,83 @@ +/* + ------------------------------------------------------------------------- + Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explcit or implied warranties + in respect of any properties, including, but not limited to, correctness + and fitness for purpose. + ------------------------------------------------------------------------- + Issue Date: 01/02/2002 + + This file contains code to obtain or set the definitions for fixed length + unsigned integer types. +*/ + +#ifndef _UITYPES_H +#define _UITYPES_H + +#include "autoconf.h" + +#if defined(__GNU_LIBRARY__) +#define HAS_INTTYPES_H +#elif !defined(_MSC_VER) +#include <limits.h> +#if ULONG_MAX > 0xFFFFFFFFUL + #define MODEL_64 +#else + #define MODEL_32 +#endif +#endif + +#if defined HAS_INTTYPES_H || defined HAVE_INTTYPES_H +#include <inttypes.h> +#define s_u32 u +#define s_u64 ull +#elif defined MODEL_32 +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long int uint64_t; +#define s_u32 u +#define s_u64 ull +#elif defined MODEL_64 +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long int uint64_t; +#define s_u32 u +#define s_u64 ul +#elif defined(_MSC_VER) +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#define s_u32 ui32 +#define s_u64 ui64 +#else +#error You need to define fixed length types in uitypes.h +#endif + +#define sfx_lo(x,y) x##y +#define sfx_hi(x,y) sfx_lo(x,y) +#define x_32(p) sfx_hi(0x##p,s_u32) +#define x_64(p) sfx_hi(0x##p,s_u64) + +#endif diff --git a/src/lib/crypto/builtin/arcfour/Makefile.in b/src/lib/crypto/builtin/arcfour/Makefile.in new file mode 100644 index 0000000..cf6c511 --- /dev/null +++ b/src/lib/crypto/builtin/arcfour/Makefile.in @@ -0,0 +1,41 @@ +thisconfigdir=../../../.. +myfulldir=lib/crypto/builtin/arcfour +mydir=lib/crypto/builtin/arcfour +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../md4 -I$(srcdir)/../../krb +DEFS= + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR=arcfour +##DOS##OBJFILE=..\$(OUTPRE)arcfour.lst + +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) + +STLIBOBJS=\ + arcfour.o \ + arcfour_aead.o \ + arcfour_s2k.o + +OBJS=\ + $(OUTPRE)arcfour.$(OBJEXT) \ + $(OUTPRE)arcfour_aead.$(OBJEXT) \ + $(OUTPRE)arcfour_s2k.$(OBJEXT) + +SRCS=\ + $(srcdir)/arcfour.c \ + $(srcdir)/arcfour_aead.c\ + $(srcdir)/arcfour_s2k.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/arcfour/arcfour-int.h b/src/lib/crypto/builtin/arcfour/arcfour-int.h new file mode 100644 index 0000000..efd7a02 --- /dev/null +++ b/src/lib/crypto/builtin/arcfour/arcfour-int.h @@ -0,0 +1,32 @@ +/* + +ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95). +This cipher is widely believed and has been tested to be equivalent +with the RC4 cipher from RSA Data Security, Inc. (RC4 is a trademark +of RSA Data Security) + +*/ +#ifndef ARCFOUR_INT_H +#define ARCFOUR_INT_H + +#include "arcfour.h" + +#define CONFOUNDERLENGTH 8 + +typedef struct +{ + unsigned int x; + unsigned int y; + unsigned char state[256]; +} ArcfourContext; + +typedef struct { + int initialized; + ArcfourContext ctx; +} ArcFourCipherState; + +krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage); + +extern const char *const krb5int_arcfour_l40; + +#endif /* ARCFOUR_INT_H */ diff --git a/src/lib/crypto/builtin/arcfour/arcfour.c b/src/lib/crypto/builtin/arcfour/arcfour.c new file mode 100644 index 0000000..87220a7 --- /dev/null +++ b/src/lib/crypto/builtin/arcfour/arcfour.c @@ -0,0 +1,335 @@ +/* + +ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95). +This cipher is widely believed and has been tested to be equivalent +with the RC4 cipher from RSA Data Security, Inc. (RC4 is a trademark +of RSA Data Security) + +*/ +#include "k5-int.h" +#include "arcfour-int.h" +#include "hash_provider/hash_provider.h" + +const char *const krb5int_arcfour_l40 = "fortybits"; + +void +krb5_arcfour_encrypt_length(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t inputlen, size_t *length) +{ + size_t blocksize, hashsize; + + blocksize = enc->block_size; + hashsize = hash->hashsize; + + /* checksum + (confounder + inputlen, in even blocksize) */ + *length = hashsize + krb5_roundup(8 + inputlen, blocksize); +} + + krb5_keyusage + krb5int_arcfour_translate_usage(krb5_keyusage usage) +{ + switch (usage) { + case 1: /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, */ + return 1; + case 2: /* ticket from kdc */ + return 2; + case 3: /* as-rep encrypted part */ + return 8; + case 4: /* tgs-req authz data */ + return 4; + case 5: /* tgs-req authz data in subkey */ + return 5; + case 6: /* tgs-req authenticator cksum */ + return 6; +case 7: /* tgs-req authenticator */ + return 7; + case 8: + return 8; + case 9: /* tgs-rep encrypted with subkey */ + return 9; + case 10: /* ap-rep authentication cksum */ + return 10; /* xxx Microsoft never uses this*/ + case 11: /* app-req authenticator */ + return 11; + case 12: /* app-rep encrypted part */ + return 12; + case 23: /* sign wrap token*/ + return 13; + default: + return usage; +} +} + +krb5_error_code +krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, krb5_keyusage usage, + const krb5_data *ivec, const krb5_data *input, + krb5_data *output) +{ + krb5_keyblock k1, k2, k3; + krb5_data d1, d2, d3, salt, plaintext, checksum, ciphertext, confounder; + krb5_keyusage ms_usage; + size_t keylength, keybytes, blocksize, hashsize; + krb5_error_code ret; + + blocksize = enc->block_size; + keybytes = enc->keybytes; + keylength = enc->keylength; + hashsize = hash->hashsize; + + d1.length=keybytes; + d1.data=malloc(d1.length); + if (d1.data == NULL) + return (ENOMEM); + k1 = *key; + k1.length=d1.length; + k1.contents= (void *) d1.data; + + d2.length=keybytes; + d2.data=malloc(d2.length); + if (d2.data == NULL) { + free(d1.data); + return (ENOMEM); + } + k2 = *key; + k2.length=d2.length; + k2.contents=(void *) d2.data; + + d3.length=keybytes; + d3.data=malloc(d3.length); + if (d3.data == NULL) { + free(d1.data); + free(d2.data); + return (ENOMEM); + } + k3 = *key; + k3.length=d3.length; + k3.contents= (void *) d3.data; + + salt.length=14; + salt.data=malloc(salt.length); + if (salt.data == NULL) { + free(d1.data); + free(d2.data); + free(d3.data); + return (ENOMEM); + } + + /* is "input" already blocksize aligned? if it is, then we need this + step, otherwise we do not */ + plaintext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize); + plaintext.data=malloc(plaintext.length); + if (plaintext.data == NULL) { + free(d1.data); + free(d2.data); + free(d3.data); + free(salt.data); + return(ENOMEM); + } + + /* setup convienient pointers into the allocated data */ + checksum.length=hashsize; + checksum.data=output->data; + ciphertext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize); + ciphertext.data=output->data+hashsize; + confounder.length=CONFOUNDERLENGTH; + confounder.data=plaintext.data; + output->length = plaintext.length+hashsize; + + /* begin the encryption, computer K1 */ + ms_usage=krb5int_arcfour_translate_usage(usage); + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, salt.data+10); + } else { + salt.length=4; + store_32_le(ms_usage, salt.data); + } + krb5_hmac(hash, key, 1, &salt, &d1); + + memcpy(k2.contents, k1.contents, k2.length); + + if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) + memset(k1.contents+7, 0xab, 9); + + ret=krb5_c_random_make_octets(/* XXX */ 0, &confounder); + memcpy(plaintext.data+confounder.length, input->data, input->length); + if (ret) + goto cleanup; + + krb5_hmac(hash, &k2, 1, &plaintext, &checksum); + + krb5_hmac(hash, &k1, 1, &checksum, &d3); + + ret=(*(enc->encrypt))(&k3, ivec, &plaintext, &ciphertext); + + cleanup: + memset(d1.data, 0, d1.length); + memset(d2.data, 0, d2.length); + memset(d3.data, 0, d3.length); + memset(salt.data, 0, salt.length); + memset(plaintext.data, 0, plaintext.length); + + free(d1.data); + free(d2.data); + free(d3.data); + free(salt.data); + free(plaintext.data); + return (ret); +} + +/* This is the arcfour-hmac decryption routine */ +krb5_error_code +krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, krb5_keyusage usage, + const krb5_data *ivec, const krb5_data *input, + krb5_data *output) +{ + krb5_keyblock k1,k2,k3; + krb5_data d1,d2,d3,salt,ciphertext,plaintext,checksum; + krb5_keyusage ms_usage; + size_t keybytes, keylength, hashsize, blocksize; + krb5_error_code ret; + + blocksize = enc->block_size; + keybytes = enc->keybytes; + keylength = enc->keylength; + hashsize = hash->hashsize; + + d1.length=keybytes; + d1.data=malloc(d1.length); + if (d1.data == NULL) + return (ENOMEM); + k1 = *key; + k1.length=d1.length; + k1.contents= (void *) d1.data; + + d2.length=keybytes; + d2.data=malloc(d2.length); + if (d2.data == NULL) { + free(d1.data); + return (ENOMEM); + } + k2 = *key; + k2.length=d2.length; + k2.contents= (void *) d2.data; + + d3.length=keybytes; + d3.data=malloc(d3.length); + if (d3.data == NULL) { + free(d1.data); + free(d2.data); + return (ENOMEM); + } + k3 = *key; + k3.length=d3.length; + k3.contents= (void *) d3.data; + + salt.length=14; + salt.data=malloc(salt.length); + if(salt.data==NULL) { + free(d1.data); + free(d2.data); + free(d3.data); + return (ENOMEM); + } + + ciphertext.length=input->length-hashsize; + ciphertext.data=input->data+hashsize; + plaintext.length=ciphertext.length; + plaintext.data=malloc(plaintext.length); + if (plaintext.data == NULL) { + free(d1.data); + free(d2.data); + free(d3.data); + free(salt.data); + return (ENOMEM); + } + + checksum.length=hashsize; + checksum.data=input->data; + + ms_usage=krb5int_arcfour_translate_usage(usage); + + /* We may have to try two ms_usage values; see below. */ + do { + /* compute the salt */ + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, salt.data + 10); + } else { + salt.length = 4; + store_32_le(ms_usage, salt.data); + } + ret = krb5_hmac(hash, key, 1, &salt, &d1); + if (ret) + goto cleanup; + + memcpy(k2.contents, k1.contents, k2.length); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + memset(k1.contents + 7, 0xab, 9); + + ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + if (ret) + goto cleanup; + + ret = (*(enc->decrypt))(&k3, ivec, &ciphertext, &plaintext); + if (ret) + goto cleanup; + + ret = krb5_hmac(hash, &k2, 1, &plaintext, &d1); + if (ret) + goto cleanup; + + if (memcmp(checksum.data, d1.data, hashsize) != 0) { + if (ms_usage == 9) { + /* + * RFC 4757 specifies usage 8 for TGS-REP encrypted + * parts encrypted in a subkey, but the value used by MS + * is actually 9. We now use 9 to start with, but fall + * back to 8 on failure in case we are communicating + * with a KDC using the value from the RFC. + */ + ms_usage = 8; + continue; + } + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + + break; + } while (1); + + memcpy(output->data, plaintext.data+CONFOUNDERLENGTH, + (plaintext.length-CONFOUNDERLENGTH)); + output->length=plaintext.length-CONFOUNDERLENGTH; + + cleanup: + memset(d1.data, 0, d1.length); + memset(d2.data, 0, d2.length); + memset(d3.data, 0, d2.length); + memset(salt.data, 0, salt.length); + memset(plaintext.data, 0, plaintext.length); + + free(d1.data); + free(d2.data); + free(d3.data); + free(salt.data); + free(plaintext.data); + return (ret); +} + + krb5_error_code krb5int_arcfour_prf( + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_data *in, krb5_data *out) + { + assert(out->length == 20); + return krb5_hmac(&krb5int_hash_sha1, key, 1, in, out); + } + diff --git a/src/lib/crypto/builtin/arcfour/arcfour.h b/src/lib/crypto/builtin/arcfour/arcfour.h new file mode 100644 index 0000000..be408fe --- /dev/null +++ b/src/lib/crypto/builtin/arcfour/arcfour.h @@ -0,0 +1,43 @@ +#ifndef ARCFOUR_H +#define ARCFOUR_H + +extern void +krb5_arcfour_encrypt_length(const struct krb5_enc_provider *, + const struct krb5_hash_provider *, + size_t, + size_t *); + +extern +krb5_error_code krb5_arcfour_encrypt(const struct krb5_enc_provider *, + const struct krb5_hash_provider *, + const krb5_keyblock *, + krb5_keyusage, + const krb5_data *, + const krb5_data *, + krb5_data *); + +extern +krb5_error_code krb5_arcfour_decrypt(const struct krb5_enc_provider *, + const struct krb5_hash_provider *, + const krb5_keyblock *, + krb5_keyusage, + const krb5_data *, + const krb5_data *, + krb5_data *); + +extern krb5_error_code krb5int_arcfour_string_to_key( + const struct krb5_enc_provider *, + const krb5_data *, + const krb5_data *, + const krb5_data *, + krb5_keyblock *); + +extern const struct krb5_enc_provider krb5int_enc_arcfour; +extern const struct krb5_aead_provider krb5int_aead_arcfour; + krb5_error_code krb5int_arcfour_prf( + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_data *in, krb5_data *out); + +#endif /* ARCFOUR_H */ diff --git a/src/lib/crypto/builtin/arcfour/arcfour_aead.c b/src/lib/crypto/builtin/arcfour/arcfour_aead.c new file mode 100644 index 0000000..cff7d66 --- /dev/null +++ b/src/lib/crypto/builtin/arcfour/arcfour_aead.c @@ -0,0 +1,325 @@ +/* + * lib/crypto/arcfour/arcfour_aead.c + * + * Copyright 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 "k5-int.h" +#include "arcfour.h" +#include "arcfour-int.h" +#include "aead.h" + +/* AEAD */ + +static krb5_error_code +krb5int_arcfour_crypto_length(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_cryptotype type, + unsigned int *length) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + *length = hash->hashsize + CONFOUNDERLENGTH; + break; + case KRB5_CRYPTO_TYPE_PADDING: + *length = 0; + break; + case KRB5_CRYPTO_TYPE_TRAILER: + *length = 0; + break; + case KRB5_CRYPTO_TYPE_CHECKSUM: + *length = hash->hashsize; + break; + default: + assert(0 && "invalid cryptotype passed to krb5int_arcfour_crypto_length"); + break; + } + + return 0; +} + +static krb5_error_code +alloc_derived_key(const struct krb5_enc_provider *enc, + krb5_keyblock *dst, + krb5_data *data, + const krb5_keyblock *src) +{ + data->length = enc->keybytes; + data->data = malloc(data->length); + if (data->data == NULL) + return ENOMEM; + + *dst = *src; + dst->length = data->length; + dst->contents = (void *)data->data; + + return 0; +} + +static krb5_error_code +krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + krb5_crypto_iov *header, *trailer; + krb5_keyblock k1, k2, k3; + krb5_data d1, d2, d3; + krb5_data checksum, confounder, header_data; + krb5_keyusage ms_usage; + char salt_data[14]; + krb5_data salt; + size_t i; + + d1.length = d2.length = d3.length = 0; + d1.data = d2.data = d3.data = NULL; + + /* + * Caller must have provided space for the header, padding + * and trailer; per RFC 4757 we will arrange it as: + * + * Checksum | E(Confounder | Plaintext) + */ + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length < hash->hashsize + CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + + header_data = header->data; + + /* Trailer may be absent */ + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL) + trailer->data.length = 0; + + /* Ensure that there is no padding */ + for (i = 0; i < num_data; i++) { + if (data[i].flags == KRB5_CRYPTO_TYPE_PADDING) + data[i].data.length = 0; + } + + ret = alloc_derived_key(enc, &k1, &d1, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k2, &d2, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k3, &d3, key); + if (ret != 0) + goto cleanup; + + /* Begin the encryption, compute K1 */ + salt.data = salt_data; + salt.length = sizeof(salt_data); + + ms_usage = krb5int_arcfour_translate_usage(usage); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, salt.data + 10); + } else { + salt.length = 4; + store_32_le(ms_usage, salt.data); + } + ret = krb5_hmac(hash, key, 1, &salt, &d1); + if (ret != 0) + goto cleanup; + + memcpy(k2.contents, k1.contents, k2.length); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + memset(k1.contents + 7, 0xAB, 9); + + header->data.length = hash->hashsize + CONFOUNDERLENGTH; + + confounder.data = header->data.data + hash->hashsize; + confounder.length = CONFOUNDERLENGTH; + + ret = krb5_c_random_make_octets(0, &confounder); + if (ret != 0) + goto cleanup; + + checksum.data = header->data.data; + checksum.length = hash->hashsize; + + /* Adjust pointers so confounder is at start of header */ + header->data.length -= hash->hashsize; + header->data.data += hash->hashsize; + + ret = krb5int_hmac_iov(hash, &k2, data, num_data, &checksum); + if (ret != 0) + goto cleanup; + + ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + if (ret != 0) + goto cleanup; + + ret = enc->encrypt_iov(&k3, ivec, data, num_data); + if (ret != 0) + goto cleanup; + +cleanup: + header->data = header_data; /* restore header pointers */ + + if (d1.data != NULL) { + memset(d1.data, 0, d1.length); + free(d1.data); + } + if (d2.data != NULL) { + memset(d2.data, 0, d2.length); + free(d2.data); + } + if (d3.data != NULL) { + memset(d3.data, 0, d3.length); + free(d3.data); + } + + return ret; +} + +static krb5_error_code +krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + krb5_crypto_iov *header, *trailer; + krb5_keyblock k1, k2, k3; + krb5_data d1, d2, d3; + krb5_data checksum, header_data; + krb5_keyusage ms_usage; + char salt_data[14]; + krb5_data salt; + + d1.length = d2.length = d3.length = 0; + d1.data = d2.data = d3.data = NULL; + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length != hash->hashsize + CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + + header_data = header->data; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL && trailer->data.length != 0) + return KRB5_BAD_MSIZE; + + ret = alloc_derived_key(enc, &k1, &d1, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k2, &d2, key); + if (ret != 0) + goto cleanup; + + ret = alloc_derived_key(enc, &k3, &d3, key); + if (ret != 0) + goto cleanup; + + /* Begin the decryption, compute K1 */ + salt.data = salt_data; + salt.length = sizeof(salt_data); + + ms_usage = krb5int_arcfour_translate_usage(usage); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, (unsigned char *)salt.data + 10); + } else { + salt.length = 4; + store_32_le(ms_usage, (unsigned char *)salt.data); + } + ret = krb5_hmac(hash, key, 1, &salt, &d1); + if (ret != 0) + goto cleanup; + + memcpy(k2.contents, k1.contents, k2.length); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + memset(k1.contents + 7, 0xAB, 9); + + checksum.data = header->data.data; + checksum.length = hash->hashsize; + + /* Adjust pointers so confounder is at start of header */ + header->data.length -= hash->hashsize; + header->data.data += hash->hashsize; + + ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + if (ret != 0) + goto cleanup; + + ret = enc->decrypt_iov(&k3, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + ret = krb5int_hmac_iov(hash, &k2, data, num_data, &d1); + if (ret != 0) + goto cleanup; + + if (memcmp(checksum.data, d1.data, hash->hashsize) != 0) { + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + +cleanup: + header->data = header_data; /* restore header pointers */ + + if (d1.data != NULL) { + memset(d1.data, 0, d1.length); + free(d1.data); + } + if (d2.data != NULL) { + memset(d2.data, 0, d2.length); + free(d2.data); + } + if (d3.data != NULL) { + memset(d3.data, 0, d3.length); + free(d3.data); + } + + return ret; +} + +const struct krb5_aead_provider krb5int_aead_arcfour = { + krb5int_arcfour_crypto_length, + krb5int_arcfour_encrypt_iov, + krb5int_arcfour_decrypt_iov +}; + diff --git a/src/lib/crypto/builtin/arcfour/arcfour_s2k.c b/src/lib/crypto/builtin/arcfour/arcfour_s2k.c new file mode 100644 index 0000000..41053ed --- /dev/null +++ b/src/lib/crypto/builtin/arcfour/arcfour_s2k.c @@ -0,0 +1,59 @@ +#include "k5-int.h" +#include "k5-utf8.h" +#include "rsa-md4.h" +#include "arcfour-int.h" + +#if TARGET_OS_MAC && !defined(DEPEND) +#include <CoreFoundation/CFString.h> +#endif + +krb5_error_code +krb5int_arcfour_string_to_key(const struct krb5_enc_provider *enc, + const krb5_data *string, const krb5_data *salt, + const krb5_data *params, krb5_keyblock *key) +{ + krb5_error_code err = 0; + krb5_MD4_CTX md4_context; + unsigned char *copystr; + size_t copystrlen; + + if (params != NULL) + return KRB5_ERR_BAD_S2K_PARAMS; + + if (key->length != 16) + return (KRB5_BAD_MSIZE); + + /* We ignore salt per the Microsoft spec*/ + + /* compute the space needed for the new string. + Since the password must be stored in unicode, we need to increase + that number by 2x. + */ + + err = krb5int_utf8cs_to_ucs2les(string->data, string->length, ©str, ©strlen); + if (err) + return err; + + /* the actual MD4 hash of the data */ + krb5_MD4Init(&md4_context); + krb5_MD4Update(&md4_context, copystr, copystrlen); + krb5_MD4Final(&md4_context); + memcpy(key->contents, md4_context.digest, 16); + +#if 0 + /* test the string_to_key function */ + printf("Hash="); + { + int counter; + for(counter=0;counter<16;counter++) + printf("%02x", md4_context.digest[counter]); + printf("\n"); + } +#endif /* 0 */ + + /* Zero out the data behind us */ + memset(copystr, 0, copystrlen); + memset(&md4_context, 0, sizeof(md4_context)); + free(copystr); + return err; +} diff --git a/src/lib/crypto/builtin/arcfour/deps b/src/lib/crypto/builtin/arcfour/deps new file mode 100644 index 0000000..a08ba44 --- /dev/null +++ b/src/lib/crypto/builtin/arcfour/deps @@ -0,0 +1,38 @@ +# +# Generated makefile dependencies follow. +# +arcfour.so arcfour.po $(OUTPRE)arcfour.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h $(srcdir)/../../krb/hash_provider/hash_provider.h \ + arcfour-int.h arcfour.c arcfour.h +arcfour_aead.so arcfour_aead.po $(OUTPRE)arcfour_aead.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + $(srcdir)/../../krb/aead.h $(srcdir)/../../krb/cksumtypes.h \ + arcfour-int.h arcfour.h arcfour_aead.c +arcfour_s2k.so arcfour_s2k.po $(OUTPRE)arcfour_s2k.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/k5-utf8.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h $(srcdir)/../md4/rsa-md4.h \ + arcfour-int.h arcfour.h arcfour_s2k.c diff --git a/src/lib/crypto/builtin/deps b/src/lib/crypto/builtin/deps new file mode 100644 index 0000000..2b5c20e --- /dev/null +++ b/src/lib/crypto/builtin/deps @@ -0,0 +1,25 @@ +# +# 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) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h $(srcdir)/../builtin/hmac.c \ + $(srcdir)/../krb/aead.h $(srcdir)/../krb/cksumtypes.h +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) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h $(srcdir)/../builtin/pbkdf2.c \ + $(srcdir)/../krb/hash_provider/hash_provider.h diff --git a/src/lib/crypto/builtin/des/ISSUES b/src/lib/crypto/builtin/des/ISSUES new file mode 100644 index 0000000..412f94a --- /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 0000000..a609c42 --- /dev/null +++ b/src/lib/crypto/builtin/des/Makefile.in @@ -0,0 +1,76 @@ +thisconfigdir=../../../.. +myfulldir=lib/crypto/builtin/des +mydir=lib/crypto/builtin/des +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../.. -I$(srcdir)/../../krb +DEFS= + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR=des +##DOS##OBJFILE=..\$(OUTPRE)des.lst + +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) + +STLIBOBJS=\ + afsstring2key.o \ + d3_cbc.o \ + d3_aead.o \ + d3_kysched.o \ + des_prf.o \ + f_aead.o \ + f_cbc.o \ + f_cksum.o \ + f_parity.o \ + f_sched.o \ + f_tables.o \ + key_sched.o \ + string2key.o \ + weak_key.o + +OBJS= $(OUTPRE)afsstring2key.$(OBJEXT) \ + $(OUTPRE)d3_cbc.$(OBJEXT) \ + $(OUTPRE)d3_aead.$(OBJEXT) \ + $(OUTPRE)d3_kysched.$(OBJEXT) \ + $(OUTPRE)des_prf.$(OBJEXT) \ + $(OUTPRE)f_aead.$(OBJEXT) \ + $(OUTPRE)f_cbc.$(OBJEXT) \ + $(OUTPRE)f_cksum.$(OBJEXT) \ + $(OUTPRE)f_parity.$(OBJEXT) \ + $(OUTPRE)f_sched.$(OBJEXT) \ + $(OUTPRE)f_tables.$(OBJEXT) \ + $(OUTPRE)key_sched.$(OBJEXT) \ + $(OUTPRE)string2key.$(OBJEXT) \ + $(OUTPRE)weak_key.$(OBJEXT) + +SRCS= $(srcdir)/afsstring2key.c \ + $(srcdir)/d3_cbc.c \ + $(srcdir)/d3_aead.c \ + $(srcdir)/d3_kysched.c \ + $(srcdir)/des_prf.c \ + $(srcdir)/f_aead.c \ + $(srcdir)/f_cbc.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 \ + $(srcdir)/string2key.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix:: all-libobjs + +includes:: depend + +depend:: $(SRCS) + +check-windows:: + +clean:: + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/src/lib/crypto/builtin/des/afsstring2key.c b/src/lib/crypto/builtin/des/afsstring2key.c new file mode 100644 index 0000000..eb6c37f --- /dev/null +++ b/src/lib/crypto/builtin/des/afsstring2key.c @@ -0,0 +1,570 @@ +/* + * lib/crypto/des/string2key.c + * + * based on lib/crypto/des/string2key.c from MIT V5 + * and on lib/des/afs_string_to_key.c from UMD. + * constructed by Mark Eichin, Cygnus Support, 1995. + * made thread-safe by Ken Raeburn, MIT, 2001. + */ + +/* + * Copyright 2001 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. + */ + +#include "k5-int.h" +#include "des_int.h" +#include <ctype.h> + +#define afs_crypt mit_afs_crypt +char *afs_crypt (const char *, const char *, char *); + +#undef min +#define min(a,b) ((a)>(b)?(b):(a)) + +krb5_error_code +mit_afs_string_to_key (krb5_keyblock *keyblock, const krb5_data *data, + const krb5_data *salt) +{ + /* totally different approach from MIT string2key. */ + /* much of the work has already been done by the only caller + which is mit_des_string_to_key; in particular, *keyblock is already + set up. */ + + char *realm = salt->data; + unsigned int i, j; + krb5_octet *key = keyblock->contents; + + if (data->length <= 8) { + /* One block only. Run afs_crypt and use the first eight + returned bytes after the copy of the (fixed) salt. + + Since the returned bytes are alphanumeric, the output is + limited to 2**48 possibilities; for each byte, only 64 + possible values can be used. */ + unsigned char password[9]; /* trailing nul for crypt() */ + char afs_crypt_buf[16]; + + memset (password, 0, sizeof (password)); + memcpy (password, realm, min (salt->length, 8)); + for (i=0; i<8; i++) + if (isupper(password[i])) + password[i] = tolower(password[i]); + for (i=0; i<data->length; i++) + password[i] ^= data->data[i]; + for (i=0; i<8; i++) + if (password[i] == '\0') + password[i] = 'X'; + password[8] = '\0'; + /* Out-of-bounds salt characters are equivalent to a salt string + of "p1". */ + strncpy((char *) key, + (char *) afs_crypt((char *) password, "#~", afs_crypt_buf) + 2, + 8); + for (i=0; i<8; i++) + key[i] <<= 1; + /* now fix up key parity again */ + mit_des_fixup_key_parity(key); + /* clean & free the input string */ + memset(password, 0, (size_t) sizeof(password)); + } else { + /* Multiple blocks. Do a CBC checksum, twice, and use the + result as the new key. */ + mit_des_cblock ikey, tkey; + mit_des_key_schedule key_sked; + unsigned int pw_len = salt->length+data->length; + unsigned char *password = malloc(pw_len+1); + if (!password) return ENOMEM; + + /* Some bound checks from the original code are elided here as + the malloc above makes sure we have enough storage. */ + memcpy (password, data->data, data->length); + for (i=data->length, j = 0; j < salt->length; i++, j++) { + password[i] = realm[j]; + if (isupper(password[i])) + password[i] = tolower(password[i]); + } + + memcpy (ikey, "kerberos", sizeof(ikey)); + memcpy (tkey, ikey, sizeof(tkey)); + mit_des_fixup_key_parity (tkey); + (void) mit_des_key_sched (tkey, key_sked); + (void) mit_des_cbc_cksum (password, tkey, i, key_sked, ikey); + + memcpy (ikey, tkey, sizeof(ikey)); + mit_des_fixup_key_parity (tkey); + (void) mit_des_key_sched (tkey, key_sked); + (void) mit_des_cbc_cksum (password, key, i, key_sked, ikey); + + /* erase key_sked */ + memset(key_sked, 0,sizeof(key_sked)); + + /* now fix up key parity again */ + mit_des_fixup_key_parity(key); + + /* clean & free the input string */ + memset(password, 0, (size_t) pw_len); + free(password); + } +#if 0 + /* must free here because it was copied for this special case */ + free(salt->data); +#endif + return 0; +} + + +/* Portions of this code: + Copyright 1989 by the Massachusetts Institute of Technology + */ + +/* + * Copyright (c) 1990 Regents of The University of Michigan. + * All Rights Reserved. + * + * 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 appears in all + * copies and that both that copyright notice and this permission + * notice appear in supporting documentation, and that the name of + * The University of Michigan not be used in advertising or + * publicity pertaining to distribution of the software without + * specific, written prior permission. This software is supplied as + * is without expressed or implied warranties of any kind. + * + * ITD Research Systems + * University of Michigan + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-936-2652 + * netatalk@terminator.cc.umich.edu + */ + +static void krb5_afs_crypt_setkey (char*, char*, char(*)[48]); +static void krb5_afs_encrypt (char*,char*,char (*)[48]); + +/* + * Initial permutation, + */ +static const char IP[] = { + 58,50,42,34,26,18,10, 2, + 60,52,44,36,28,20,12, 4, + 62,54,46,38,30,22,14, 6, + 64,56,48,40,32,24,16, 8, + 57,49,41,33,25,17, 9, 1, + 59,51,43,35,27,19,11, 3, + 61,53,45,37,29,21,13, 5, + 63,55,47,39,31,23,15, 7, +}; + +/* + * Final permutation, FP = IP^(-1) + */ +static const char FP[] = { + 40, 8,48,16,56,24,64,32, + 39, 7,47,15,55,23,63,31, + 38, 6,46,14,54,22,62,30, + 37, 5,45,13,53,21,61,29, + 36, 4,44,12,52,20,60,28, + 35, 3,43,11,51,19,59,27, + 34, 2,42,10,50,18,58,26, + 33, 1,41, 9,49,17,57,25, +}; + +/* + * Permuted-choice 1 from the key bits to yield C and D. + * Note that bits 8,16... are left out: They are intended for a parity check. + */ +static const char PC1_C[] = { + 57,49,41,33,25,17, 9, + 1,58,50,42,34,26,18, + 10, 2,59,51,43,35,27, + 19,11, 3,60,52,44,36, +}; + +static const char PC1_D[] = { + 63,55,47,39,31,23,15, + 7,62,54,46,38,30,22, + 14, 6,61,53,45,37,29, + 21,13, 5,28,20,12, 4, +}; + +/* + * Sequence of shifts used for the key schedule. + */ +static const char shifts[] = { + 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1, +}; + +/* + * Permuted-choice 2, to pick out the bits from + * the CD array that generate the key schedule. + */ +static const char PC2_C[] = { + 14,17,11,24, 1, 5, + 3,28,15, 6,21,10, + 23,19,12, 4,26, 8, + 16, 7,27,20,13, 2, +}; + +static const char PC2_D[] = { + 41,52,31,37,47,55, + 30,40,51,45,33,48, + 44,49,39,56,34,53, + 46,42,50,36,29,32, +}; + +/* + * The E bit-selection table. + */ +static const char e[] = { + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9,10,11,12,13, + 12,13,14,15,16,17, + 16,17,18,19,20,21, + 20,21,22,23,24,25, + 24,25,26,27,28,29, + 28,29,30,31,32, 1, +}; + +/* + * P is a permutation on the selected combination + * of the current L and key. + */ +static const char P[] = { + 16, 7,20,21, + 29,12,28,17, + 1,15,23,26, + 5,18,31,10, + 2, 8,24,14, + 32,27, 3, 9, + 19,13,30, 6, + 22,11, 4,25, +}; + +/* + * The 8 selection functions. + * For some reason, they give a 0-origin + * index, unlike everything else. + */ +static const char S[8][64] = { + {14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7, + 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8, + 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0, + 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13}, + + {15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10, + 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5, + 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15, + 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9}, + + {10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1, + 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7, + 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12}, + + { 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15, + 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9, + 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4, + 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14}, + + { 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9, + 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6, + 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14, + 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3}, + + {12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11, + 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8, + 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6, + 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13}, + + { 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1, + 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6, + 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2, + 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12}, + + {13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7, + 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2, + 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8, + 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11}, +}; + + +char *afs_crypt(const char *pw, const char *salt, + /* must be at least 16 bytes */ + char *iobuf) +{ + int i, j, c; + int temp; + char block[66]; + char E[48]; + /* + * The key schedule. + * Generated from the key. + */ + char KS[16][48]; + + for(i=0; i<66; i++) + block[i] = 0; + for(i=0; (c= *pw) && i<64; pw++){ + for(j=0; j<7; j++, i++) + block[i] = (c>>(6-j)) & 01; + i++; + } + + krb5_afs_crypt_setkey(block, E, KS); + + for(i=0; i<66; i++) + block[i] = 0; + + for(i=0;i<2;i++){ + c = *salt++; + iobuf[i] = c; + if(c>'Z') c -= 6; + if(c>'9') c -= 7; + c -= '.'; + for(j=0;j<6;j++){ + if((c>>j) & 01){ + temp = E[6*i+j]; + E[6*i+j] = E[6*i+j+24]; + E[6*i+j+24] = temp; + } + } + } + + for(i=0; i<25; i++) + krb5_afs_encrypt(block,E,KS); + + for(i=0; i<11; i++){ + c = 0; + for(j=0; j<6; j++){ + c <<= 1; + c |= block[6*i+j]; + } + c += '.'; + if(c>'9') c += 7; + if(c>'Z') c += 6; + iobuf[i+2] = c; + } + iobuf[i+2] = 0; + if(iobuf[1]==0) + iobuf[1] = iobuf[0]; + return(iobuf); +} + +/* + * Set up the key schedule from the key. + */ + +static void krb5_afs_crypt_setkey(char *key, char *E, char (*KS)[48]) +{ + register int i, j, k; + int t; + /* + * The C and D arrays used to calculate the key schedule. + */ + char C[28], D[28]; + + /* + * First, generate C and D by permuting + * the key. The low order bit of each + * 8-bit char is not used, so C and D are only 28 + * bits apiece. + */ + for (i=0; i<28; i++) { + C[i] = key[PC1_C[i]-1]; + D[i] = key[PC1_D[i]-1]; + } + /* + * To generate Ki, rotate C and D according + * to schedule and pick up a permutation + * using PC2. + */ + for (i=0; i<16; i++) { + /* + * rotate. + */ + for (k=0; k<shifts[i]; k++) { + t = C[0]; + for (j=0; j<28-1; j++) + C[j] = C[j+1]; + C[27] = t; + t = D[0]; + for (j=0; j<28-1; j++) + D[j] = D[j+1]; + D[27] = t; + } + /* + * get Ki. Note C and D are concatenated. + */ + for (j=0; j<24; j++) { + KS[i][j] = C[PC2_C[j]-1]; + KS[i][j+24] = D[PC2_D[j]-28-1]; + } + } + +#if 0 + for(i=0;i<48;i++) { + E[i] = e[i]; + } +#else + memcpy(E, e, 48); +#endif +} + +/* + * The payoff: encrypt a block. + */ + +static void krb5_afs_encrypt(char *block, char *E, char (*KS)[48]) +{ + const long edflag = 0; + int i, ii; + int t, j, k; + char tempL[32]; + char f[32]; + /* + * The current block, divided into 2 halves. + */ + char L[64]; + char *const R = &L[32]; + /* + * The combination of the key and the input, before selection. + */ + char preS[48]; + + /* + * First, permute the bits in the input + */ + for (j=0; j<64; j++) + L[j] = block[IP[j]-1]; + /* + * Perform an encryption operation 16 times. + */ + for (ii=0; ii<16; ii++) { + /* + * Set direction + */ + if (edflag) + i = 15-ii; + else + i = ii; + /* + * Save the R array, + * which will be the new L. + */ +#if 0 + for (j=0; j<32; j++) + tempL[j] = R[j]; +#else + memcpy(tempL, R, 32); +#endif + /* + * Expand R to 48 bits using the E selector; + * exclusive-or with the current key bits. + */ + for (j=0; j<48; j++) + preS[j] = R[E[j]-1] ^ KS[i][j]; + /* + * The pre-select bits are now considered + * in 8 groups of 6 bits each. + * The 8 selection functions map these + * 6-bit quantities into 4-bit quantities + * and the results permuted + * to make an f(R, K). + * The indexing into the selection functions + * is peculiar; it could be simplified by + * rewriting the tables. + */ + for (j=0; j<8; j++) { + t = 6*j; + k = S[j][(preS[t+0]<<5)+ + (preS[t+1]<<3)+ + (preS[t+2]<<2)+ + (preS[t+3]<<1)+ + (preS[t+4]<<0)+ + (preS[t+5]<<4)]; + t = 4*j; + f[t+0] = (k>>3)&01; + f[t+1] = (k>>2)&01; + f[t+2] = (k>>1)&01; + f[t+3] = (k>>0)&01; + } + /* + * The new R is L ^ f(R, K). + * The f here has to be permuted first, though. + */ + for (j=0; j<32; j++) + R[j] = L[j] ^ f[P[j]-1]; + /* + * Finally, the new L (the original R) + * is copied back. + */ +#if 0 + for (j=0; j<32; j++) + L[j] = tempL[j]; +#else + memcpy(L, tempL, 32); +#endif + } + /* + * The output L and R are reversed. + */ + for (j=0; j<32; j++) { + t = L[j]; + L[j] = R[j]; + R[j] = t; + } + /* + * The final output + * gets the inverse permutation of the very original. + */ + for (j=0; j<64; j++) + block[j] = L[FP[j]-1]; +} 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 0000000..2245283 --- /dev/null +++ b/src/lib/crypto/builtin/des/d3_aead.c @@ -0,0 +1,207 @@ +/* + * 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 "des_int.h" +#include "f_tables.h" +#include "aead.h" + +void +krb5int_des3_cbc_encrypt_iov(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 char *op; + struct iov_block_state input_pos, output_pos; + unsigned char iblock[MIT_DES_BLOCK_LENGTH]; + unsigned char oblock[MIT_DES_BLOCK_LENGTH]; + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + /* + * Get key pointer here. This 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. + */ + if (ivec != NULL) + ip = ivec; + else + ip = mit_des_zeroblock; + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + + /* + * Suitably initialized, now work the length down 8 bytes + * at a time. + */ + for (;;) { + unsigned DES_INT32 temp; + + ip = iblock; + op = oblock; + + if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos)) + break; + + if (input_pos.iov_pos == num_data) + break; + + GET_HALF_BLOCK(temp, ip); + left ^= temp; + GET_HALF_BLOCK(temp, ip); + right ^= temp; + + /* + * Encrypt what we have + */ + DES_DO_ENCRYPT(left, right, kp1); + DES_DO_DECRYPT(left, right, kp2); + DES_DO_ENCRYPT(left, right, kp3); + + /* + * Copy the results out + */ + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + + krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos); + } + + if (ivec != NULL) + memcpy(ivec, oblock, MIT_DES_BLOCK_LENGTH); +} + +void +krb5int_des3_cbc_decrypt_iov(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; + unsigned char *op; + struct iov_block_state input_pos, output_pos; + unsigned char iblock[MIT_DES_BLOCK_LENGTH]; + unsigned char oblock[MIT_DES_BLOCK_LENGTH]; + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + /* + * Get key pointer here. This 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... + */ + + if (num_data == 0) + return; + + /* + * Prime the old cipher with ivec. + */ + if (ivec != NULL) + ip = ivec; + else + ip = mit_des_zeroblock; + GET_HALF_BLOCK(ocipherl, ip); + GET_HALF_BLOCK(ocipherr, ip); + + /* + * Now do this in earnest until we run out of length. + */ + for (;;) { + /* + * Read a block from the input into left and + * right. Save this cipher block for later. + */ + + if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos)) + break; + + if (input_pos.iov_pos == num_data) + break; + + ip = iblock; + op = oblock; + + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + cipherl = left; + cipherr = right; + + /* + * Decrypt this. + */ + DES_DO_DECRYPT(left, right, kp3); + DES_DO_ENCRYPT(left, right, kp2); + DES_DO_DECRYPT(left, right, kp1); + + /* + * Xor with the old cipher to get plain + * text. Output 8 or less bytes of this. + */ + left ^= ocipherl; + right ^= ocipherr; + + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + + /* + * Save current cipher block here + */ + ocipherl = cipherl; + ocipherr = cipherr; + + krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos); + } + + if (ivec != NULL) { + op = ivec; + PUT_HALF_BLOCK(ocipherl,op); + PUT_HALF_BLOCK(ocipherr, op); + } +} diff --git a/src/lib/crypto/builtin/des/d3_cbc.c b/src/lib/crypto/builtin/des/d3_cbc.c new file mode 100644 index 0000000..077e78d --- /dev/null +++ b/src/lib/crypto/builtin/des/d3_cbc.c @@ -0,0 +1,223 @@ +/* + * 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 "des_int.h" +#include "f_tables.h" + +/* + * Triple-DES CBC encryption mode. + */ + +#undef mit_des3_cbc_encrypt +int +mit_des3_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, + unsigned long length, const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec, int enc) +{ + if (enc) + krb5int_des3_cbc_encrypt(in, out, length, ks1, ks2, ks3, ivec); + else + krb5int_des3_cbc_decrypt(in, out, length, ks1, ks2, ks3, ivec); + return 0; +} + +void +krb5int_des3_cbc_encrypt(const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp1, *kp2, *kp3; + const unsigned char *ip; + unsigned char *op; + + /* + * Get key pointer here. This 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; + 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; + + } + length = 0; + } + + /* + * Encrypt what we have + */ + DES_DO_ENCRYPT(left, right, kp1); + DES_DO_DECRYPT(left, right, kp2); + DES_DO_ENCRYPT(left, right, kp3); + + /* + * Copy the results out + */ + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + } +} + +void +krb5int_des3_cbc_decrypt(const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp1, *kp2, *kp3; + 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 + */ + 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... + */ + + 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, kp3); + DES_DO_ENCRYPT(left, right, kp2); + DES_DO_DECRYPT(left, right, kp1); + + /* + * 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; /* we're done */ + } + } +} 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 0000000..f18cc24 --- /dev/null +++ b/src/lib/crypto/builtin/des/d3_kysched.c @@ -0,0 +1,50 @@ +/* + * 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 0000000..9a57423 --- /dev/null +++ b/src/lib/crypto/builtin/des/deps @@ -0,0 +1,158 @@ +# +# Generated makefile dependencies follow. +# +afsstring2key.so afsstring2key.po $(OUTPRE)afsstring2key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + afsstring2key.c des_int.h +d3_cbc.so d3_cbc.po $(OUTPRE)d3_cbc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h d3_cbc.c des_int.h \ + f_tables.h +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) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h $(srcdir)/../../krb/aead.h \ + $(srcdir)/../../krb/cksumtypes.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) $(SRCTOP)/include/autoconf.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + d3_kysched.c des_int.h +des_prf.so des_prf.po $(OUTPRE)des_prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h $(srcdir)/../../krb/hash_provider/hash_provider.h \ + des_prf.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) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h $(srcdir)/../../krb/aead.h \ + $(srcdir)/../../krb/cksumtypes.h des_int.h f_aead.c \ + f_tables.h +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) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h des_int.h f_cbc.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) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h 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) $(SRCTOP)/include/autoconf.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + 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) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h 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) $(SRCTOP)/include/autoconf.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + 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) $(SRCTOP)/include/autoconf.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + 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) $(SRCTOP)/include/autoconf.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + des_int.h weak_key.c +string2key.so string2key.po $(OUTPRE)string2key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ + $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ + $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ + des_int.h string2key.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 0000000..4a1d52a --- /dev/null +++ b/src/lib/crypto/builtin/des/des_int.h @@ -0,0 +1,382 @@ +/* + * lib/crypto/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. + * + * + * Private include file for the Data Encryption Standard library. + */ + +/* + * 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. + */ + +/* 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)) + +/* + * Check if k5-int.h has been included before us. If so, then check to see + * that our view of the DES key size is the same as k5-int.h's. + */ +#ifdef KRB5_MIT_DES_KEYSIZE +#if MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE +error(MIT_DES_KEYSIZE does not equal KRB5_MIT_DES_KEYSIZE) +#endif /* MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE */ +#endif /* KRB5_MIT_DES_KEYSIZE */ +#endif /* KRB5_MIT_DES__ */ +/* + * End "mit-des.h" + */ + +/* afsstring2key.c */ +extern krb5_error_code mit_afs_string_to_key + (krb5_keyblock *keyblock, + const krb5_data *data, + const krb5_data *salt); +extern char *mit_afs_crypt + (const char *pw, const char *salt, char *iobuf); + +/* f_cksum.c */ +extern unsigned long mit_des_cbc_cksum + (const krb5_octet *, krb5_octet *, unsigned long , + const mit_des_key_schedule, const krb5_octet *); + +/* f_ecb.c */ +extern int mit_des_ecb_encrypt + (const mit_des_cblock *, mit_des_cblock *, mit_des_key_schedule , int ); + +/* f_cbc.c */ +extern 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 */ +extern krb5_error_code mit_des_finish_random_key + ( const krb5_encrypt_block *, + krb5_pointer *); + +/* finish_key.c */ +extern krb5_error_code mit_des_finish_key + ( krb5_encrypt_block *); + +/* init_rkey.c */ +extern krb5_error_code mit_des_init_random_key + ( const krb5_encrypt_block *, + const krb5_keyblock *, + krb5_pointer *); + +/* key_parity.c */ +extern void mit_des_fixup_key_parity (mit_des_cblock ); +extern int mit_des_check_key_parity (mit_des_cblock ); + +/* key_sched.c */ +extern int mit_des_key_sched + (mit_des_cblock , mit_des_key_schedule ); + +/* process_ky.c */ +extern krb5_error_code mit_des_process_key + ( krb5_encrypt_block *, const krb5_keyblock *); + +/* random_key.c */ +extern krb5_error_code mit_des_random_key + ( const krb5_encrypt_block *, krb5_pointer , + krb5_keyblock **); + +/* string2key.c */ +extern krb5_error_code mit_des_string_to_key + ( const krb5_encrypt_block *, + krb5_keyblock *, const krb5_data *, const krb5_data *); +extern krb5_error_code mit_des_string_to_key_int + (krb5_keyblock *, const krb5_data *, const krb5_data *); + +/* weak_key.c */ +extern 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 + +/* d3_ecb.c */ +extern int mit_des3_ecb_encrypt + (const mit_des_cblock *in, + mit_des_cblock *out, + mit_des_key_schedule sched1, + mit_des_key_schedule sched2, + mit_des_key_schedule sched3, + int enc); + +/* d3_cbc.c */ +extern int mit_des3_cbc_encrypt + (const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec, + int enc); + +void +krb5int_des3_cbc_encrypt(const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec); +void +krb5int_des3_cbc_decrypt(const mit_des_cblock *in, + mit_des_cblock *out, + unsigned long length, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + const mit_des_cblock ivec); + +void +krb5int_des3_cbc_encrypt_iov(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_iov(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); + +#define mit_des3_cbc_encrypt(in,out,length,ks1,ks2,ks3,ivec,enc) \ + ((enc ? krb5int_des3_cbc_encrypt : krb5int_des3_cbc_decrypt) \ + (in, out, length, ks1, ks2, ks3, ivec), 0) + +void +krb5int_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); +void +krb5int_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); + +#define mit_des_cbc_encrypt(in,out,length,schedule,ivec,enc) \ + ((enc ? krb5int_des_cbc_encrypt : krb5int_des_cbc_decrypt) \ + (in, out, length, schedule, ivec), 0) + +void +krb5int_des_cbc_encrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec); + +void +krb5int_des_cbc_decrypt_iov(krb5_crypto_iov *data, + unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec); + +/* d3_procky.c */ +extern krb5_error_code mit_des3_process_key + (krb5_encrypt_block * eblock, + const krb5_keyblock * keyblock); + +/* d3_kysched.c */ +extern int mit_des3_key_sched + (mit_des3_cblock key, + mit_des3_key_schedule schedule); + +/* d3_str2ky.c */ +extern 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 */ +extern 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 */ +extern int mit_des_is_weak_keyblock + (krb5_keyblock *keyblock); + +extern void mit_des_fixup_keyblock_parity + (krb5_keyblock *keyblock); + +extern krb5_error_code mit_des_set_random_generator_seed + (const krb5_data * seed, + krb5_pointer random_state); + +extern krb5_error_code mit_des_set_random_sequence_number + (const krb5_data * sequence, + krb5_pointer random_state); +krb5_error_code +krb5int_des_prf (const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_data *in, krb5_data *out); +#endif /*DES_INTERNAL_DEFS*/ diff --git a/src/lib/crypto/builtin/des/des_prf.c b/src/lib/crypto/builtin/des/des_prf.c new file mode 100644 index 0000000..a86ba90 --- /dev/null +++ b/src/lib/crypto/builtin/des/des_prf.c @@ -0,0 +1,54 @@ +/* + * lib/crypto/des/des_prf.c + * + * Copyright (C) 2004, 2009 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 file contains an implementation of the RFC 3961 PRF for + * des-cbc-crc, des-cbc-md4, and des-cbc-md5 enctypes. + */ + +#include "k5-int.h" +#include "hash_provider/hash_provider.h" /* XXX is this ok? */ + +krb5_error_code +krb5int_des_prf (const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_data *in, krb5_data *out) +{ + krb5_data tmp; + krb5_error_code ret = 0; + + hash = &krb5int_hash_md5; /* MD5 is always used. */ + tmp.length = hash->hashsize; + tmp.data = malloc(hash->hashsize); + if (tmp.data == NULL) + return ENOMEM; + ret = hash->hash(1, in, &tmp); + if (ret == 0) + ret = enc->encrypt(key, NULL, &tmp, out); + free(tmp.data); + return ret; +} 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 0000000..70f9f33 --- /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 0000000..170482c --- /dev/null +++ b/src/lib/crypto/builtin/des/f_aead.c @@ -0,0 +1,192 @@ +/* + * 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 "des_int.h" +#include "f_tables.h" +#include "aead.h" + +void +krb5int_des_cbc_encrypt_iov(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 char *op; + struct iov_block_state input_pos, output_pos; + unsigned char iblock[MIT_DES_BLOCK_LENGTH]; + unsigned char oblock[MIT_DES_BLOCK_LENGTH]; + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + /* + * 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. + */ + if (ivec != NULL) + ip = ivec; + else + ip = mit_des_zeroblock; + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + + /* + * Suitably initialized, now work the length down 8 bytes + * at a time. + */ + for (;;) { + unsigned DES_INT32 temp; + + ip = iblock; + op = oblock; + + if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos)) + break; + + if (input_pos.iov_pos == num_data) + break; + + GET_HALF_BLOCK(temp, ip); + left ^= temp; + GET_HALF_BLOCK(temp, ip); + right ^= temp; + + /* + * Encrypt what we have + */ + DES_DO_ENCRYPT(left, right, kp); + + /* + * Copy the results out + */ + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + + krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos); + } + + if (ivec != NULL) + memcpy(ivec, oblock, MIT_DES_BLOCK_LENGTH); +} + +void +krb5int_des_cbc_decrypt_iov(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; + unsigned char *op; + struct iov_block_state input_pos, output_pos; + unsigned char iblock[MIT_DES_BLOCK_LENGTH]; + unsigned char oblock[MIT_DES_BLOCK_LENGTH]; + + IOV_BLOCK_STATE_INIT(&input_pos); + IOV_BLOCK_STATE_INIT(&output_pos); + + /* + * 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 (num_data == 0) + return; + + /* + * Prime the old cipher with ivec. + */ + if (ivec != NULL) + ip = ivec; + else + ip = mit_des_zeroblock; + GET_HALF_BLOCK(ocipherl, ip); + GET_HALF_BLOCK(ocipherr, ip); + + /* + * Now do this in earnest until we run out of length. + */ + for (;;) { + /* + * Read a block from the input into left and + * right. Save this cipher block for later. + */ + + if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos)) + break; + + if (input_pos.iov_pos == num_data) + break; + + ip = iblock; + op = oblock; + + 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; + + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + + /* + * Save current cipher block here + */ + ocipherl = cipherl; + ocipherr = cipherr; + + krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos); + } + + if (ivec != NULL) + memcpy(ivec, oblock, MIT_DES_BLOCK_LENGTH); +} 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 0000000..0949ba1 --- /dev/null +++ b/src/lib/crypto/builtin/des/f_cbc.c @@ -0,0 +1,274 @@ +/* + * lib/crypto/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. + * + * DES implementation donated by Dennis Ferguson + */ + +/* + * 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 */; + +#undef mit_des_cbc_encrypt +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) + krb5int_des_cbc_encrypt(in, out, length, schedule, ivec); + else + krb5int_des_cbc_decrypt(in, out, length, schedule, ivec); + return 0; +} + +void +krb5int_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); + } +} + +void +krb5int_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 */ + } + } +} + +#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_cksum.c b/src/lib/crypto/builtin/des/f_cksum.c new file mode 100644 index 0000000..1c03da4 --- /dev/null +++ b/src/lib/crypto/builtin/des/f_cksum.c @@ -0,0 +1,136 @@ +/* + * lib/crypto/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 0000000..4263863 --- /dev/null +++ b/src/lib/crypto/builtin/des/f_parity.c @@ -0,0 +1,56 @@ +/* + * 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 0000000..ece48ef --- /dev/null +++ b/src/lib/crypto/builtin/des/f_sched.c @@ -0,0 +1,359 @@ +/* + * lib/crypto/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 0000000..42426bc --- /dev/null +++ b/src/lib/crypto/builtin/des/f_tables.c @@ -0,0 +1,370 @@ +/* + * lib/crypto/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 0000000..45a6322 --- /dev/null +++ b/src/lib/crypto/builtin/des/f_tables.h @@ -0,0 +1,279 @@ +/* + * lib/crypto/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) \ + (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] + +#define DES_SP_DECRYPT_ROUND(left, right, temp, kp) \ + (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] + +/* + * 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) \ + (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) + +/* + * 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) \ + (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] + + +/* + * 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 0000000..26449a9 --- /dev/null +++ b/src/lib/crypto/builtin/des/key_sched.c @@ -0,0 +1,61 @@ +/* + * lib/crypto/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/string2key.c b/src/lib/crypto/builtin/des/string2key.c new file mode 100644 index 0000000..0ce4136 --- /dev/null +++ b/src/lib/crypto/builtin/des/string2key.c @@ -0,0 +1,261 @@ +/* + * lib/crypto/des/des_s2k.c + * + * Copyright 2004, 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. + * + * + * Compute encryption key from salt and pass phrase. + */ + +#include "k5-int.h" +#include "des_int.h" + +krb5_error_code +mit_des_string_to_key_int (krb5_keyblock *key, + const krb5_data *pw, const krb5_data *salt) +{ + union { + /* 8 "forward" bytes, 8 "reverse" bytes */ + unsigned char uc[16]; + krb5_ui_4 ui[4]; + mit_des_cblock cb; + } temp; + unsigned int i; + krb5_ui_4 x, y, z; + unsigned char *p; + des_key_schedule sched; + char *copy; + size_t copylen; + + /* As long as the architecture is big-endian or little-endian, it + doesn't matter which it is. Think of it as reversing the + bytes, and also reversing the bits within each byte. But this + current algorithm is dependent on having four 8-bit char values + exactly overlay a 32-bit integral type. */ + if (sizeof(temp.uc) != sizeof(temp.ui) + || (unsigned char)~0 != 0xFF + || (krb5_ui_4)~(krb5_ui_4)0 != 0xFFFFFFFF + || (temp.uc[0] = 1, temp.uc[1] = 2, temp.uc[2] = 3, temp.uc[3] = 4, + !(temp.ui[0] == 0x01020304 + || temp.ui[0] == 0x04030201))) + abort(); +#define FETCH4(VAR, IDX) VAR = temp.ui[IDX/4] +#define PUT4(VAR, IDX) temp.ui[IDX/4] = VAR + + if (salt + && (salt->length == SALT_TYPE_AFS_LENGTH + /* XXX Yuck! Aren't we done with this yet? */ + || salt->length == (unsigned) -1)) { + krb5_data afssalt; + char *at; + + afssalt.data = salt->data; + at = strchr(afssalt.data, '@'); + if (at) { + *at = 0; + afssalt.length = at - afssalt.data; + } else + afssalt.length = strlen(afssalt.data); + return mit_afs_string_to_key(key, pw, &afssalt); + } + + copylen = pw->length + (salt ? salt->length : 0); + /* Don't need NUL termination, at this point we're treating it as + a byte array, not a string. */ + copy = malloc(copylen); + if (copy == NULL) + return ENOMEM; + memcpy(copy, pw->data, pw->length); + if (salt) + memcpy(copy + pw->length, salt->data, salt->length); + + memset(&temp, 0, sizeof(temp)); + p = temp.uc; + /* Handle the fan-fold xor operation by splitting the data into + forward and reverse sections, and combine them later, rather + than having to do the reversal over and over again. */ + for (i = 0; i < copylen; i++) { + *p++ ^= copy[i]; + if (p == temp.uc+16) { + p = temp.uc; +#ifdef PRINT_TEST_VECTORS + { + int j; + printf("after %d input bytes:\nforward block:\t", i+1); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\nreverse block:\t"); + for (j = 8; j < 16; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif + } + } + +#ifdef PRINT_TEST_VECTORS + if (p != temp.uc) { + int j; + printf("at end, after %d input bytes:\nforward block:\t", i); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\nreverse block:\t"); + for (j = 8; j < 16; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif +#if 0 + /* Algorithm described in Dr. Dobbs Journal 1983, reported in "bit + twiddling hacks" web page collected by Sean Eron Anderson; see + http://graphics.stanford.edu/~seander/bithacks.html for + details. + + Avoids loops, uses 7*lg(N)=35 ops instead of 4*N=128 for the + obvious mask, ior, shift, shift sequence of each 32-bit + quantity. + + If we could rely on 64-bit math, another 7 ops would save us + from having to do double the work. */ +#define REVERSE_STEP(VAR, SHIFT, MASK) \ + VAR = ((VAR >> SHIFT) & MASK) | ((VAR << SHIFT) & (0xFFFFFFFFUL & ~MASK)) +#define REVERSE(VAR) \ + REVERSE_STEP (VAR, 1, 0x55555555UL); /* swap odd/even bits */ \ + REVERSE_STEP (VAR, 2, 0x33333333UL); /* swap bitpairs */ \ + REVERSE_STEP (VAR, 4, 0x0F0F0F0FUL); /* swap nibbles, etc */ \ + REVERSE_STEP (VAR, 8, 0x00FF00FFUL); \ + REVERSE_STEP (VAR, 16, 0x0000FFFFUL); +#else /* shorter */ +#define REVERSE(VAR) \ + { \ + krb5_ui_4 old = VAR, temp1 = 0; \ + int j; \ + for (j = 0; j < 32; j++) { \ + temp1 = (temp1 << 1) | (old & 1); \ + old >>= 1; \ + } \ + VAR = temp1; \ + } +#endif + + FETCH4 (x, 8); + FETCH4 (y, 12); + /* Ignore high bits of each input byte. */ + x &= 0x7F7F7F7F; + y &= 0x7F7F7F7F; + /* Reverse the bit strings -- after this, y is "before" x. */ + REVERSE (x); + REVERSE (y); +#ifdef PRINT_TEST_VECTORS + { + int j; + union { unsigned char uc[4]; krb5_ui_4 ui; } t2; + printf("after reversal, reversed block:\n\t\t"); + t2.ui = y; + for (j = 0; j < 4; j++) + printf(" %02x", t2.uc[j] & 0xff); + t2.ui = x; + for (j = 0; j < 4; j++) + printf(" %02x", t2.uc[j] & 0xff); + printf("\n"); + } +#endif + /* Ignored bits are now at the bottom of each byte, where we'll + put the parity bits. Good. */ + FETCH4 (z, 0); + z &= 0x7F7F7F7F; + /* Ignored bits for z are at the top of each byte; fix that. */ + z <<= 1; + /* Finish the fan-fold xor for these four bytes. */ + z ^= y; + PUT4 (z, 0); + /* Now do the second four bytes. */ + FETCH4 (z, 4); + z &= 0x7F7F7F7F; + /* Ignored bits for z are at the top of each byte; fix that. */ + z <<= 1; + /* Finish the fan-fold xor for these four bytes. */ + z ^= x; + PUT4 (z, 4); + +#ifdef PRINT_TEST_VECTORS + { + int j; + printf("after reversal, combined block:\n\t\t"); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif + +#define FIXUP(K) \ + (mit_des_fixup_key_parity(K), \ + mit_des_is_weak_key(K) ? (K[7] ^= 0xF0) : 0) + + /* Now temp.cb is the temporary key, with invalid parity. */ + FIXUP(temp.cb); + +#ifdef PRINT_TEST_VECTORS + { + int j; + printf("after fixing parity and weak keys:\n\t\t"); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif + + mit_des_key_sched(temp.cb, sched); + mit_des_cbc_cksum(copy, temp.cb, copylen, sched, temp.cb); + + memset(copy, 0, copylen); + free(copy); + +#ifdef PRINT_TEST_VECTORS + { + int j; + printf("cbc checksum:\n\t\t"); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif + + memset(sched, 0, sizeof(sched)); + FIXUP (temp.cb); + +#ifdef PRINT_TEST_VECTORS + { + int j; + printf("after fixing parity and weak keys:\n\t\t"); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif + + memcpy(key->contents, temp.cb, 8); + memset(&temp, 0, sizeof(temp)); + + return 0; +} 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 0000000..2eab9f5 --- /dev/null +++ b/src/lib/crypto/builtin/des/weak_key.c @@ -0,0 +1,85 @@ +/* + * lib/crypto/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/hmac.c b/src/lib/crypto/builtin/hmac.c new file mode 100644 index 0000000..3bff3cf --- /dev/null +++ b/src/lib/crypto/builtin/hmac.c @@ -0,0 +1,165 @@ +/* + * 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 "k5-int.h" +#include "aead.h" + +/* + * 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 +krb5_hmac(const struct krb5_hash_provider *hash, const krb5_keyblock *key, + unsigned int icount, const krb5_data *input, krb5_data *output) +{ + size_t hashsize, blocksize; + unsigned char *xorkey, *ihash; + unsigned int i; + krb5_data *hashin, hashout; + krb5_error_code ret; + + hashsize = hash->hashsize; + blocksize = hash->blocksize; + + if (key->length > blocksize) + return(KRB5_CRYPTO_INTERNAL); + if (output->length < hashsize) + return(KRB5_BAD_MSIZE); + /* if this isn't > 0, then there won't be enough space in this + array to compute the outer hash */ + if (icount == 0) + return(KRB5_CRYPTO_INTERNAL); + + /* allocate space for the xor key, hash input vector, and inner hash */ + + if ((xorkey = (unsigned char *) malloc(blocksize)) == NULL) + return(ENOMEM); + if ((ihash = (unsigned char *) malloc(hashsize)) == NULL) { + free(xorkey); + return(ENOMEM); + } + if ((hashin = (krb5_data *)malloc(sizeof(krb5_data)*(icount+1))) == NULL) { + free(ihash); + free(xorkey); + return(ENOMEM); + } + + /* create the inner padded key */ + + memset(xorkey, 0x36, blocksize); + + for (i=0; i<key->length; i++) + xorkey[i] ^= key->contents[i]; + + /* compute the inner hash */ + + hashin[0].length = blocksize; + hashin[0].data = (char *) xorkey; + for (i=0; i<icount; i++) + hashin[i+1] = input[i]; + + hashout.length = hashsize; + hashout.data = (char *) ihash; + + if ((ret = ((*(hash->hash))(icount+1, hashin, &hashout)))) + goto cleanup; + + /* create the outer padded key */ + + memset(xorkey, 0x5c, blocksize); + + for (i=0; i<key->length; i++) + xorkey[i] ^= key->contents[i]; + + /* compute the outer hash */ + + hashin[0].length = blocksize; + hashin[0].data = (char *) xorkey; + hashin[1] = hashout; + + output->length = hashsize; + + if ((ret = ((*(hash->hash))(2, hashin, output)))) + memset(output->data, 0, output->length); + + /* ret is set correctly by the prior call */ + +cleanup: + memset(xorkey, 0, blocksize); + memset(ihash, 0, hashsize); + + free(hashin); + free(ihash); + free(xorkey); + + return(ret); +} + +krb5_error_code +krb5int_hmac_iov(const struct krb5_hash_provider *hash, const krb5_keyblock *key, + const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + krb5_data *sign_data; + size_t num_sign_data; + krb5_error_code ret; + size_t i, j; + + /* Create a checksum over all the data to be signed */ + for (i = 0, num_sign_data = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) + num_sign_data++; + } + + /* XXX cleanup to avoid alloc */ + sign_data = (krb5_data *)calloc(num_sign_data, sizeof(krb5_data)); + if (sign_data == NULL) + return ENOMEM; + + for (i = 0, j = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) + sign_data[j++] = iov->data; + } + + /* caller must store checksum in iov as it may be TYPE_TRAILER or TYPE_CHECKSUM */ + ret = krb5_hmac(hash, key, num_sign_data, sign_data, output); + + free(sign_data); + + return ret; +} + diff --git a/src/lib/crypto/builtin/md4/ISSUES b/src/lib/crypto/builtin/md4/ISSUES new file mode 100644 index 0000000..1103bd8 --- /dev/null +++ b/src/lib/crypto/builtin/md4/ISSUES @@ -0,0 +1,3 @@ +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 0000000..78dd053 --- /dev/null +++ b/src/lib/crypto/builtin/md4/Makefile.in @@ -0,0 +1,39 @@ +thisconfigdir=../../../.. +myfulldir=lib/crypto/builtin/md4 +mydir=lib/crypto/builtin/md4 +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir) +DEFS= + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR=md4 +##DOS##OBJFILE=..\$(OUTPRE)md4.lst + +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) + +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 0000000..1decaf9 --- /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) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h 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 0000000..7922c71 --- /dev/null +++ b/src/lib/crypto/builtin/md4/md4.c @@ -0,0 +1,246 @@ +/* + * lib/crypto/md4/md4.c + */ + +/* + ********************************************************************** + ** 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 ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** 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. ** + ********************************************************************** + */ + +#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 +krb5_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 +krb5_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 +krb5_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); + krb5_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 0000000..d4e6f6b --- /dev/null +++ b/src/lib/crypto/builtin/md4/rsa-md4.h @@ -0,0 +1,94 @@ +/* + * lib/crypto/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. + * + * + * 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 ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** 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. ** + ********************************************************************** + */ + +/* 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 krb5_MD4Init(krb5_MD4_CTX *); +extern void krb5_MD4Update(krb5_MD4_CTX *, const unsigned char *, unsigned int); +extern void krb5_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 0000000..481e529 --- /dev/null +++ b/src/lib/crypto/builtin/md5/ISSUES @@ -0,0 +1,3 @@ +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 0000000..6da4374 --- /dev/null +++ b/src/lib/crypto/builtin/md5/Makefile.in @@ -0,0 +1,37 @@ +thisconfigdir=../../../.. +myfulldir=lib/crypto/builtin/md5 +mydir=lib/crypto/builtin/md5 +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +DEFS= + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR=md5 +##DOS##OBJFILE=..\$(OUTPRE)md5.lst + +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) + +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 0000000..fc3378d --- /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) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h 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 0000000..e548dbc --- /dev/null +++ b/src/lib/crypto/builtin/md5/md5.c @@ -0,0 +1,343 @@ +/* + *********************************************************************** + ** 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. + */ + +/* + *********************************************************************** + ** 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. ** + *********************************************************************** + */ + +#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 krb5_MD5Init ** + ** (2) Call krb5_MD5Update on mdContext and M ** + ** (3) Call krb5_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 krb5_MD5Init initializes the message-digest context + mdContext. All fields are set to zero. + */ +void +krb5_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 krb5_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 +krb5_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 krb5_MD5Final terminates the message-digest computation and + ends with the desired message digest in mdContext->digest[0...15]. + */ +void +krb5_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); + krb5_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 0000000..846b238 --- /dev/null +++ b/src/lib/crypto/builtin/md5/rsa-md5.h @@ -0,0 +1,60 @@ +/* + *********************************************************************** + ** 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 ** + *********************************************************************** + */ + +/* + *********************************************************************** + ** 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. ** + *********************************************************************** + */ + +#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 krb5_MD5Init(krb5_MD5_CTX *); +extern void krb5_MD5Update(krb5_MD5_CTX *,const unsigned char *,unsigned int); +extern void krb5_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 0000000..d897e9a --- /dev/null +++ b/src/lib/crypto/builtin/pbkdf2.c @@ -0,0 +1,265 @@ +/* + * lib/crypto/pbkdf2.c + * + * 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. + * + * + * Implementation of PBKDF2 from RFC 2898. + * Not currently used; likely to be used when we get around to AES support. + */ + +#include <ctype.h> +#include "k5-int.h" +#include "hash_provider.h" + +/* Not exported, for now. */ +static krb5_error_code +krb5int_pbkdf2 (krb5_error_code (*prf)(krb5_keyblock *, krb5_data *, + krb5_data *), + size_t hlen, const krb5_data *pass, const krb5_data *salt, + unsigned long count, const krb5_data *output); + +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"); +} +static void printk(const char *descr, krb5_keyblock *k) { + krb5_data d; + d.data = (char *) k->contents; + d.length = k->length; + printd(descr, &d); +} + +static krb5_error_code +F(char *output, char *u_tmp1, char *u_tmp2, + krb5_error_code (*prf)(krb5_keyblock *, krb5_data *, krb5_data *), + size_t hlen, + const krb5_data *pass, const krb5_data *salt, + unsigned long count, int i) +{ + unsigned char ibytes[4]; + size_t tlen; + unsigned int j, k; + krb5_keyblock pdata; + krb5_data sdata; + krb5_data out; + krb5_error_code err; + + pdata.contents = pass->data; + pdata.length = pass->length; + +#if 0 + printf("F(i=%d, count=%lu, pass=%d:%s)\n", i, count, + pass->length, pass->data); + printk("F password", &pdata); +#endif + + /* Compute U_1. */ + store_32_be(i, ibytes); + + tlen = salt->length; + memcpy(u_tmp2, salt->data, tlen); + memcpy(u_tmp2 + tlen, ibytes, 4); + tlen += 4; + sdata.data = u_tmp2; + sdata.length = tlen; + +#if 0 + printd("initial salt", &sdata); +#endif + + out.data = u_tmp1; + out.length = hlen; + +#if 0 + printf("F: computing hmac #1 (U_1) with %s\n", pdata.contents); +#endif + err = (*prf)(&pdata, &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 = (*prf)(&pdata, &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 +krb5int_pbkdf2 (krb5_error_code (*prf)(krb5_keyblock *, krb5_data *, + krb5_data *), + size_t hlen, + const krb5_data *pass, const krb5_data *salt, + unsigned long count, const krb5_data *output) +{ + int l, r, i; + char *utmp1, *utmp2; + char utmp3[20]; /* 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; + r = output->length - (l - 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, prf, 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; +} + +static krb5_error_code hmac1(const struct krb5_hash_provider *h, + krb5_keyblock *key, krb5_data *in, krb5_data *out) +{ + char tmp[40]; + size_t blocksize, hashsize; + krb5_error_code err; + krb5_keyblock k; + + k = *key; + key = &k; + if (debug_hmac) + printk(" test key", key); + blocksize = h->blocksize; + hashsize = h->hashsize; + if (hashsize > sizeof(tmp)) + abort(); + if (key->length > blocksize) { + krb5_data d, d2; + d.data = (char *) key->contents; + d.length = key->length; + d2.data = tmp; + d2.length = hashsize; + err = h->hash (1, &d, &d2); + if (err) + return err; + key->length = d2.length; + key->contents = (krb5_octet *) d2.data; + if (debug_hmac) + printk(" pre-hashed key", key); + } + if (debug_hmac) + printd(" hmac input", in); + err = krb5_hmac(h, key, 1, in, out); + if (err == 0 && debug_hmac) + printd(" hmac output", out); + return err; +} + +static krb5_error_code +foo(krb5_keyblock *pass, krb5_data *salt, krb5_data *out) +{ + krb5_error_code err; + + memset(out->data, 0, out->length); + err = hmac1 (&krb5int_hash_sha1, pass, salt, out); + return err; +} + +krb5_error_code +krb5int_pbkdf2_hmac_sha1 (const krb5_data *out, unsigned long count, + const krb5_data *pass, const krb5_data *salt) +{ + return krb5int_pbkdf2 (foo, 20, pass, salt, count, out); +} diff --git a/src/lib/crypto/builtin/sha1/ISSUES b/src/lib/crypto/builtin/sha1/ISSUES new file mode 100644 index 0000000..8b7e8a2 --- /dev/null +++ b/src/lib/crypto/builtin/sha1/ISSUES @@ -0,0 +1,7 @@ +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 0000000..81776f5 --- /dev/null +++ b/src/lib/crypto/builtin/sha1/Makefile.in @@ -0,0 +1,37 @@ +thisconfigdir=../../../.. +myfulldir=lib/crypto/builtin/sha1 +mydir=lib/crypto/builtin/sha1 +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +DEFS= + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR=sha1 +##DOS##OBJFILE=..\$(OUTPRE)sha1.lst + +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) + +STLIBOBJS= shs.o + +OBJS= $(OUTPRE)shs.$(OBJEXT) + +SRCS= $(srcdir)/shs.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/sha1/deps b/src/lib/crypto/builtin/sha1/deps new file mode 100644 index 0000000..a8f51a8 --- /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) $(SRCTOP)/include/autoconf.h \ + $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h 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 0000000..d9372df --- /dev/null +++ b/src/lib/crypto/builtin/sha1/shs.c @@ -0,0 +1,381 @@ +#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 0000000..6dcb41b --- /dev/null +++ b/src/lib/crypto/builtin/sha1/shs.h @@ -0,0 +1,45 @@ +#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 */ |