aboutsummaryrefslogtreecommitdiff
path: root/src/lib/crypto/krb
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2009-09-13 02:52:23 +0000
committerGreg Hudson <ghudson@mit.edu>2009-09-13 02:52:23 +0000
commit0e39f8a3ad915eeb0131fb4a87b0fef304101cfd (patch)
tree6c6d7fd4b23f4724156300b5505433b13cfe9fb6 /src/lib/crypto/krb
parentf89b62fe9fd7b0cb10d7e2ff542fb18c1b56d35d (diff)
downloadkrb5-0e39f8a3ad915eeb0131fb4a87b0fef304101cfd.zip
krb5-0e39f8a3ad915eeb0131fb4a87b0fef304101cfd.tar.gz
krb5-0e39f8a3ad915eeb0131fb4a87b0fef304101cfd.tar.bz2
Implement s4u extensions
Merge Luke's users/lhoward/s4u branch to trunk. Implements S4U2Self and S4U2Proxy extensions. ticket: 6563 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22736 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/crypto/krb')
-rw-r--r--src/lib/crypto/krb/enc_provider/Makefile.in41
-rw-r--r--src/lib/crypto/krb/enc_provider/aes.c415
-rw-r--r--src/lib/crypto/krb/enc_provider/deps49
-rw-r--r--src/lib/crypto/krb/enc_provider/des.c181
-rw-r--r--src/lib/crypto/krb/enc_provider/des3.c221
-rw-r--r--src/lib/crypto/krb/enc_provider/enc_provider.h36
-rw-r--r--src/lib/crypto/krb/enc_provider/rc4.c271
7 files changed, 1214 insertions, 0 deletions
diff --git a/src/lib/crypto/krb/enc_provider/Makefile.in b/src/lib/crypto/krb/enc_provider/Makefile.in
new file mode 100644
index 0000000..2eedf1d
--- /dev/null
+++ b/src/lib/crypto/krb/enc_provider/Makefile.in
@@ -0,0 +1,41 @@
+thisconfigdir=../../../..
+myfulldir=lib/crypto/krb/enc_provider
+mydir=lib/crypto/krb/enc_provider
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/../../@CRYPTO_IMPL@/des -I$(srcdir)/../../@CRYPTO_IMPL@/arcfour \
+ -I$(srcdir)/../../@CRYPTO_IMPL@/aes -I$(srcdir)/.. -I$(srcdir)/../../@CRYPTO_IMPL@
+DEFS=
+
+##DOS##BUILDTOP = ..\..\..\..
+##DOS##PREFIXDIR=enc_provider
+##DOS##OBJFILE=..\$(OUTPRE)enc_prov.lst
+
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+STLIBOBJS= des.o des3.o rc4.o aes.o
+
+OBJS= \
+ $(OUTPRE)des.$(OBJEXT) \
+ $(OUTPRE)des3.$(OBJEXT) \
+ $(OUTPRE)aes.$(OBJEXT) \
+ $(OUTPRE)rc4.$(OBJEXT)
+
+SRCS= \
+ $(srcdir)/des.c \
+ $(srcdir)/des3.c \
+ $(srcdir)/aes.c \
+ $(srcdir)/rc4.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix:: all-libobjs
+
+includes:: depend
+
+depend:: $(SRCS)
+
+clean-unix:: clean-libobjs
+
+@libobj_frag@
+
diff --git a/src/lib/crypto/krb/enc_provider/aes.c b/src/lib/crypto/krb/enc_provider/aes.c
new file mode 100644
index 0000000..060d119
--- /dev/null
+++ b/src/lib/crypto/krb/enc_provider/aes.c
@@ -0,0 +1,415 @@
+/*
+ * lib/crypto/enc_provider/aes.c
+ *
+ * Copyright (C) 2003, 2007, 2008 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-int.h"
+#include "enc_provider.h"
+#include "aes.h"
+#include "../aead.h"
+
+#if 0
+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]);
+#endif
+
+#define CHECK_SIZES 0
+
+#if 0
+static void printd (const char *descr, krb5_data *d) {
+ 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]);
+#ifdef SHOW_TEXT
+ 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 : '.');
+ }
+#endif
+ }
+ printf("\n");
+}
+#endif
+
+static inline void enc(char *out, const char *in, aes_ctx *ctx)
+{
+ if (aes_enc_blk((const unsigned char *)in, (unsigned char *)out, ctx)
+ != aes_good)
+ abort();
+}
+static inline void dec(char *out, const char *in, aes_ctx *ctx)
+{
+ if (aes_dec_blk((const unsigned char *)in, (unsigned char *)out, ctx)
+ != aes_good)
+ abort();
+}
+
+static void xorblock(char *out, const char *in)
+{
+ int z;
+ for (z = 0; z < BLOCK_SIZE; z++)
+ out[z] ^= in[z];
+}
+
+krb5_error_code
+krb5int_aes_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ aes_ctx ctx;
+ char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE];
+ int nblocks = 0, blockno;
+
+/* CHECK_SIZES; */
+
+ if (aes_enc_key(key->contents, key->length, &ctx) != aes_good)
+ abort();
+
+ if (ivec)
+ memcpy(tmp, ivec->data, BLOCK_SIZE);
+ else
+ memset(tmp, 0, BLOCK_SIZE);
+
+ nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+ if (nblocks == 1) {
+ /* XXX Used for DK function. */
+ enc(output->data, input->data, &ctx);
+ } else {
+ unsigned int nleft;
+
+ for (blockno = 0; blockno < nblocks - 2; blockno++) {
+ xorblock(tmp, input->data + blockno * BLOCK_SIZE);
+ enc(tmp2, tmp, &ctx);
+ memcpy(output->data + blockno * BLOCK_SIZE, tmp2, BLOCK_SIZE);
+
+ /* Set up for next block. */
+ memcpy(tmp, tmp2, BLOCK_SIZE);
+ }
+ /* Do final CTS step for last two blocks (the second of which
+ may or may not be incomplete). */
+ xorblock(tmp, input->data + (nblocks - 2) * BLOCK_SIZE);
+ enc(tmp2, tmp, &ctx);
+ nleft = input->length - (nblocks - 1) * BLOCK_SIZE;
+ memcpy(output->data + (nblocks - 1) * BLOCK_SIZE, tmp2, nleft);
+ memcpy(tmp, tmp2, BLOCK_SIZE);
+
+ memset(tmp3, 0, sizeof(tmp3));
+ memcpy(tmp3, input->data + (nblocks - 1) * BLOCK_SIZE, nleft);
+ xorblock(tmp, tmp3);
+ enc(tmp2, tmp, &ctx);
+ memcpy(output->data + (nblocks - 2) * BLOCK_SIZE, tmp2, BLOCK_SIZE);
+ if (ivec)
+ memcpy(ivec->data, tmp2, BLOCK_SIZE);
+ }
+
+ return 0;
+}
+
+krb5_error_code
+krb5int_aes_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ aes_ctx ctx;
+ char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE];
+ int nblocks = 0, blockno;
+
+ CHECK_SIZES;
+
+ if (aes_dec_key(key->contents, key->length, &ctx) != aes_good)
+ abort();
+
+ if (ivec)
+ memcpy(tmp, ivec->data, BLOCK_SIZE);
+ else
+ memset(tmp, 0, BLOCK_SIZE);
+
+ nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+ if (nblocks == 1) {
+ if (input->length < BLOCK_SIZE)
+ abort();
+ dec(output->data, input->data, &ctx);
+ } else {
+
+ for (blockno = 0; blockno < nblocks - 2; blockno++) {
+ dec(tmp2, input->data + blockno * BLOCK_SIZE, &ctx);
+ xorblock(tmp2, tmp);
+ memcpy(output->data + blockno * BLOCK_SIZE, tmp2, BLOCK_SIZE);
+ memcpy(tmp, input->data + blockno * BLOCK_SIZE, BLOCK_SIZE);
+ }
+ /* Do last two blocks, the second of which (next-to-last block
+ of plaintext) may be incomplete. */
+ dec(tmp2, input->data + (nblocks - 2) * BLOCK_SIZE, &ctx);
+ /* Set tmp3 to last ciphertext block, padded. */
+ memset(tmp3, 0, sizeof(tmp3));
+ memcpy(tmp3, input->data + (nblocks - 1) * BLOCK_SIZE,
+ input->length - (nblocks - 1) * BLOCK_SIZE);
+ /* Set tmp2 to last (possibly partial) plaintext block, and
+ save it. */
+ xorblock(tmp2, tmp3);
+ memcpy(output->data + (nblocks - 1) * BLOCK_SIZE, tmp2,
+ input->length - (nblocks - 1) * BLOCK_SIZE);
+ /* Maybe keep the trailing part, and copy in the last
+ ciphertext block. */
+ memcpy(tmp2, tmp3, input->length - (nblocks - 1) * BLOCK_SIZE);
+ /* Decrypt, to get next to last plaintext block xor previous
+ ciphertext. */
+ dec(tmp3, tmp2, &ctx);
+ xorblock(tmp3, tmp);
+ memcpy(output->data + (nblocks - 2) * BLOCK_SIZE, tmp3, BLOCK_SIZE);
+ if (ivec)
+ memcpy(ivec->data, input->data + (nblocks - 2) * BLOCK_SIZE,
+ BLOCK_SIZE);
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+krb5int_aes_encrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ aes_ctx ctx;
+ char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE];
+ int nblocks = 0, blockno;
+ size_t input_length, i;
+
+ if (aes_enc_key(key->contents, key->length, &ctx) != aes_good)
+ abort();
+
+ if (ivec != NULL)
+ memcpy(tmp, ivec->data, BLOCK_SIZE);
+ else
+ memset(tmp, 0, BLOCK_SIZE);
+
+ for (i = 0, input_length = 0; i < num_data; i++) {
+ krb5_crypto_iov *iov = &data[i];
+
+ if (ENCRYPT_IOV(iov))
+ input_length += iov->data.length;
+ }
+
+ nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+ assert(nblocks > 1);
+
+ {
+ char blockN2[BLOCK_SIZE]; /* second last */
+ char blockN1[BLOCK_SIZE]; /* last block */
+ struct iov_block_state input_pos, output_pos;
+
+ IOV_BLOCK_STATE_INIT(&input_pos);
+ IOV_BLOCK_STATE_INIT(&output_pos);
+
+ for (blockno = 0; blockno < nblocks - 2; blockno++) {
+ char blockN[BLOCK_SIZE];
+
+ krb5int_c_iov_get_block((unsigned char *)blockN, BLOCK_SIZE, data, num_data, &input_pos);
+ xorblock(tmp, blockN);
+ enc(tmp2, tmp, &ctx);
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)tmp2, BLOCK_SIZE, &output_pos);
+
+ /* Set up for next block. */
+ memcpy(tmp, tmp2, BLOCK_SIZE);
+ }
+
+ /* Do final CTS step for last two blocks (the second of which
+ may or may not be incomplete). */
+
+ /* First, get the last two blocks */
+ memset(blockN1, 0, sizeof(blockN1)); /* pad last block with zeros */
+ krb5int_c_iov_get_block((unsigned char *)blockN2, BLOCK_SIZE, data, num_data, &input_pos);
+ krb5int_c_iov_get_block((unsigned char *)blockN1, BLOCK_SIZE, data, num_data, &input_pos);
+
+ /* Encrypt second last block */
+ xorblock(tmp, blockN2);
+ enc(tmp2, tmp, &ctx);
+ memcpy(blockN2, tmp2, BLOCK_SIZE); /* blockN2 now contains first block */
+ memcpy(tmp, tmp2, BLOCK_SIZE);
+
+ /* Encrypt last block */
+ xorblock(tmp, blockN1);
+ enc(tmp2, tmp, &ctx);
+ memcpy(blockN1, tmp2, BLOCK_SIZE);
+
+ /* Put the last two blocks back into the iovec (reverse order) */
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN1, BLOCK_SIZE, &output_pos);
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN2, BLOCK_SIZE, &output_pos);
+
+ if (ivec != NULL)
+ memcpy(ivec->data, blockN1, BLOCK_SIZE);
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+krb5int_aes_decrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ aes_ctx ctx;
+ char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE];
+ int nblocks = 0, blockno;
+ unsigned int i;
+ size_t input_length;
+
+ CHECK_SIZES;
+
+ if (aes_dec_key(key->contents, key->length, &ctx) != aes_good)
+ abort();
+
+ if (ivec != NULL)
+ memcpy(tmp, ivec->data, BLOCK_SIZE);
+ else
+ memset(tmp, 0, BLOCK_SIZE);
+
+ for (i = 0, input_length = 0; i < num_data; i++) {
+ krb5_crypto_iov *iov = &data[i];
+
+ if (ENCRYPT_IOV(iov))
+ input_length += iov->data.length;
+ }
+
+ nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+ assert(nblocks > 1);
+
+ {
+ char blockN2[BLOCK_SIZE]; /* second last */
+ char blockN1[BLOCK_SIZE]; /* last block */
+ struct iov_block_state input_pos, output_pos;
+
+ IOV_BLOCK_STATE_INIT(&input_pos);
+ IOV_BLOCK_STATE_INIT(&output_pos);
+
+ for (blockno = 0; blockno < nblocks - 2; blockno++) {
+ char blockN[BLOCK_SIZE];
+
+ krb5int_c_iov_get_block((unsigned char *)blockN, BLOCK_SIZE, data, num_data, &input_pos);
+ dec(tmp2, blockN, &ctx);
+ xorblock(tmp2, tmp);
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)tmp2, BLOCK_SIZE, &output_pos);
+ memcpy(tmp, blockN, BLOCK_SIZE);
+ }
+
+ /* Do last two blocks, the second of which (next-to-last block
+ of plaintext) may be incomplete. */
+
+ /* First, get the last two encrypted blocks */
+ memset(blockN1, 0, sizeof(blockN1)); /* pad last block with zeros */
+ krb5int_c_iov_get_block((unsigned char *)blockN2, BLOCK_SIZE, data, num_data, &input_pos);
+ krb5int_c_iov_get_block((unsigned char *)blockN1, BLOCK_SIZE, data, num_data, &input_pos);
+
+ /* Decrypt second last block */
+ dec(tmp2, blockN2, &ctx);
+ /* Set tmp2 to last (possibly partial) plaintext block, and
+ save it. */
+ xorblock(tmp2, blockN1);
+ memcpy(blockN2, tmp2, BLOCK_SIZE);
+
+ /* Maybe keep the trailing part, and copy in the last
+ ciphertext block. */
+ input_length %= BLOCK_SIZE;
+ memcpy(tmp2, blockN1, input_length ? input_length : BLOCK_SIZE);
+ dec(tmp3, tmp2, &ctx);
+ xorblock(tmp3, tmp);
+ /* Copy out ivec first before we clobber blockN1 with plaintext */
+ if (ivec != NULL)
+ memcpy(ivec->data, blockN1, BLOCK_SIZE);
+ memcpy(blockN1, tmp3, BLOCK_SIZE);
+
+ /* Put the last two blocks back into the iovec */
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN1, BLOCK_SIZE, &output_pos);
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN2, BLOCK_SIZE, &output_pos);
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+k5_aes_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+ if (key->length != 16 && key->length != 32)
+ return(KRB5_BAD_KEYSIZE);
+ if (randombits->length != key->length)
+ return(KRB5_CRYPTO_INTERNAL);
+
+ key->magic = KV5M_KEYBLOCK;
+
+ memcpy(key->contents, randombits->data, randombits->length);
+ return(0);
+}
+
+static krb5_error_code
+krb5int_aes_init_state (const krb5_keyblock *key, krb5_keyusage usage,
+ krb5_data *state)
+{
+ state->length = 16;
+ state->data = (void *) malloc(16);
+ if (state->data == NULL)
+ return ENOMEM;
+ memset(state->data, 0, state->length);
+ return 0;
+}
+
+const struct krb5_enc_provider krb5int_enc_aes128 = {
+ 16,
+ 16, 16,
+ krb5int_aes_encrypt,
+ krb5int_aes_decrypt,
+ k5_aes_make_key,
+ krb5int_aes_init_state,
+ krb5int_default_free_state,
+ krb5int_aes_encrypt_iov,
+ krb5int_aes_decrypt_iov
+};
+
+const struct krb5_enc_provider krb5int_enc_aes256 = {
+ 16,
+ 32, 32,
+ krb5int_aes_encrypt,
+ krb5int_aes_decrypt,
+ k5_aes_make_key,
+ krb5int_aes_init_state,
+ krb5int_default_free_state,
+ krb5int_aes_encrypt_iov,
+ krb5int_aes_decrypt_iov
+};
+
diff --git a/src/lib/crypto/krb/enc_provider/deps b/src/lib/crypto/krb/enc_provider/deps
new file mode 100644
index 0000000..0649762
--- /dev/null
+++ b/src/lib/crypto/krb/enc_provider/deps
@@ -0,0 +1,49 @@
+#
+# Generated makefile dependencies follow.
+#
+des.so des.po $(OUTPRE)des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(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/des/des_int.h $(srcdir)/../aead.h \
+ $(srcdir)/../cksumtypes.h des.c enc_provider.h
+des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(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/des/des_int.h $(srcdir)/../aead.h \
+ $(srcdir)/../cksumtypes.h des3.c
+aes.so aes.po $(OUTPRE)aes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(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/aes/aes.h $(srcdir)/../../builtin/aes/uitypes.h \
+ $(srcdir)/../aead.h $(srcdir)/../cksumtypes.h aes.c \
+ enc_provider.h
+rc4.so rc4.po $(OUTPRE)rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(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/arcfour/arcfour-int.h $(srcdir)/../../builtin/arcfour/arcfour.h \
+ $(srcdir)/../aead.h $(srcdir)/../cksumtypes.h enc_provider.h \
+ rc4.c
diff --git a/src/lib/crypto/krb/enc_provider/des.c b/src/lib/crypto/krb/enc_provider/des.c
new file mode 100644
index 0000000..547f6b9
--- /dev/null
+++ b/src/lib/crypto/krb/enc_provider/des.c
@@ -0,0 +1,181 @@
+/*
+ * 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 "enc_provider.h"
+#include "aead.h"
+
+static krb5_error_code
+k5_des_docrypt(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output, int enc)
+{
+ mit_des_key_schedule schedule;
+
+ /* key->enctype was checked by the caller */
+
+ if (key->length != 8)
+ return(KRB5_BAD_KEYSIZE);
+ if ((input->length%8) != 0)
+ return(KRB5_BAD_MSIZE);
+ if (ivec && (ivec->length != 8))
+ return(KRB5_BAD_MSIZE);
+ if (input->length != output->length)
+ return(KRB5_BAD_MSIZE);
+
+ switch (mit_des_key_sched(key->contents, schedule)) {
+ case -1:
+ return(KRB5DES_BAD_KEYPAR);
+ case -2:
+ return(KRB5DES_WEAK_KEY);
+ }
+
+ /* this has a return value, but the code always returns zero */
+
+ mit_des_cbc_encrypt((krb5_pointer) input->data,
+ (krb5_pointer) output->data, input->length,
+ schedule,
+ (ivec
+ ? (const unsigned char *) ivec->data
+ : (const unsigned char *) mit_des_zeroblock),
+ enc);
+
+ memset(schedule, 0, sizeof(schedule));
+
+ return(0);
+}
+
+static krb5_error_code
+k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ return(k5_des_docrypt(key, ivec, input, output, 1));
+}
+
+static krb5_error_code
+k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ return(k5_des_docrypt(key, ivec, input, output, 0));
+}
+
+static krb5_error_code
+k5_des_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+ if (key->length != 8)
+ return(KRB5_BAD_KEYSIZE);
+ if (randombits->length != 7)
+ return(KRB5_CRYPTO_INTERNAL);
+
+ key->magic = KV5M_KEYBLOCK;
+ key->length = 8;
+
+ /* take the seven bytes, move them around into the top 7 bits of the
+ 8 key bytes, then compute the parity bits */
+
+ memcpy(key->contents, randombits->data, randombits->length);
+ key->contents[7] = (((key->contents[0]&1)<<1) | ((key->contents[1]&1)<<2) |
+ ((key->contents[2]&1)<<3) | ((key->contents[3]&1)<<4) |
+ ((key->contents[4]&1)<<5) | ((key->contents[5]&1)<<6) |
+ ((key->contents[6]&1)<<7));
+
+ mit_des_fixup_key_parity(key->contents);
+
+ return(0);
+}
+
+static krb5_error_code
+k5_des_docrypt_iov(const krb5_keyblock *key, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data, int enc)
+{
+ mit_des_key_schedule schedule;
+ size_t input_length = 0;
+ unsigned int i;
+
+ /* key->enctype was checked by the caller */
+
+ if (key->length != 8)
+ return(KRB5_BAD_KEYSIZE);
+
+ for (i = 0; i < num_data; i++) {
+ const krb5_crypto_iov *iov = &data[i];
+
+ if (ENCRYPT_DATA_IOV(iov))
+ input_length += iov->data.length;
+ }
+
+ if ((input_length % 8) != 0)
+ return(KRB5_BAD_MSIZE);
+ if (ivec && (ivec->length != 8))
+ return(KRB5_BAD_MSIZE);
+
+ switch (mit_des_key_sched(key->contents, schedule)) {
+ case -1:
+ return(KRB5DES_BAD_KEYPAR);
+ case -2:
+ return(KRB5DES_WEAK_KEY);
+ }
+
+ /* this has a return value, but the code always returns zero */
+ if (enc)
+ krb5int_des_cbc_encrypt_iov(data, num_data, schedule, ivec ? ivec->data : NULL);
+ else
+ krb5int_des_cbc_decrypt_iov(data, num_data, schedule, ivec ? ivec->data : NULL);
+
+ memset(schedule, 0, sizeof(schedule));
+
+ return(0);
+}
+
+static krb5_error_code
+k5_des_encrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ return k5_des_docrypt_iov(key, ivec, data, num_data, 1);
+}
+
+static krb5_error_code
+k5_des_decrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ return k5_des_docrypt_iov(key, ivec, data, num_data, 0);
+}
+
+const struct krb5_enc_provider krb5int_enc_des = {
+ 8,
+ 7, 8,
+ k5_des_encrypt,
+ k5_des_decrypt,
+ k5_des_make_key,
+ krb5int_des_init_state,
+ krb5int_default_free_state,
+ k5_des_encrypt_iov,
+ k5_des_decrypt_iov
+};
diff --git a/src/lib/crypto/krb/enc_provider/des3.c b/src/lib/crypto/krb/enc_provider/des3.c
new file mode 100644
index 0000000..412c994
--- /dev/null
+++ b/src/lib/crypto/krb/enc_provider/des3.c
@@ -0,0 +1,221 @@
+/*
+ * 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 "../aead.h"
+
+static krb5_error_code
+validate_and_schedule(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, const krb5_data *output,
+ mit_des3_key_schedule *schedule)
+{
+ /* key->enctype was checked by the caller */
+
+ if (key->length != 24)
+ return(KRB5_BAD_KEYSIZE);
+ if ((input->length%8) != 0)
+ return(KRB5_BAD_MSIZE);
+ if (ivec && (ivec->length != 8))
+ return(KRB5_BAD_MSIZE);
+ if (input->length != output->length)
+ return(KRB5_BAD_MSIZE);
+
+ switch (mit_des3_key_sched(*(mit_des3_cblock *)key->contents,
+ *schedule)) {
+ case -1:
+ return(KRB5DES_BAD_KEYPAR);
+ case -2:
+ return(KRB5DES_WEAK_KEY);
+ }
+ return 0;
+}
+
+static krb5_error_code
+validate_and_schedule_iov(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_crypto_iov *data, size_t num_data,
+ mit_des3_key_schedule *schedule)
+{
+ size_t i, input_length;
+
+ for (i = 0, input_length = 0; i < num_data; i++) {
+ const krb5_crypto_iov *iov = &data[i];
+
+ if (ENCRYPT_IOV(iov))
+ input_length += iov->data.length;
+ }
+
+ if (key->length != 24)
+ return(KRB5_BAD_KEYSIZE);
+ if ((input_length%8) != 0)
+ return(KRB5_BAD_MSIZE);
+ if (ivec && (ivec->length != 8))
+ return(KRB5_BAD_MSIZE);
+
+ switch (mit_des3_key_sched(*(mit_des3_cblock *)key->contents,
+ *schedule)) {
+ case -1:
+ return(KRB5DES_BAD_KEYPAR);
+ case -2:
+ return(KRB5DES_WEAK_KEY);
+ }
+ return 0;
+}
+
+static krb5_error_code
+k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ mit_des3_key_schedule schedule;
+ krb5_error_code err;
+
+ err = validate_and_schedule(key, ivec, input, output, &schedule);
+ if (err)
+ return err;
+
+ /* this has a return value, but the code always returns zero */
+ krb5int_des3_cbc_encrypt((krb5_pointer) input->data,
+ (krb5_pointer) output->data, input->length,
+ schedule[0], schedule[1], schedule[2],
+ ivec?(const unsigned char *) ivec->data:(const unsigned char *)mit_des_zeroblock);
+
+ zap(schedule, sizeof(schedule));
+
+ return(0);
+}
+
+static krb5_error_code
+k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ mit_des3_key_schedule schedule;
+ krb5_error_code err;
+
+ err = validate_and_schedule(key, ivec, input, output, &schedule);
+ if (err)
+ return err;
+
+ /* this has a return value, but the code always returns zero */
+ krb5int_des3_cbc_decrypt((krb5_pointer) input->data,
+ (krb5_pointer) output->data, input->length,
+ schedule[0], schedule[1], schedule[2],
+ ivec?(const unsigned char *) ivec->data:(const unsigned char *)mit_des_zeroblock);
+
+ zap(schedule, sizeof(schedule));
+
+ return(0);
+}
+
+static krb5_error_code
+k5_des3_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+ int i;
+
+ if (key->length != 24)
+ return(KRB5_BAD_KEYSIZE);
+ if (randombits->length != 21)
+ return(KRB5_CRYPTO_INTERNAL);
+
+ key->magic = KV5M_KEYBLOCK;
+ key->length = 24;
+
+ /* take the seven bytes, move them around into the top 7 bits of the
+ 8 key bytes, then compute the parity bits. Do this three times. */
+
+ for (i=0; i<3; i++) {
+ memcpy(key->contents+i*8, randombits->data+i*7, 7);
+ key->contents[i*8+7] = (((key->contents[i*8]&1)<<1) |
+ ((key->contents[i*8+1]&1)<<2) |
+ ((key->contents[i*8+2]&1)<<3) |
+ ((key->contents[i*8+3]&1)<<4) |
+ ((key->contents[i*8+4]&1)<<5) |
+ ((key->contents[i*8+5]&1)<<6) |
+ ((key->contents[i*8+6]&1)<<7));
+
+ mit_des_fixup_key_parity(key->contents+i*8);
+ }
+
+ return(0);
+}
+
+static krb5_error_code
+k5_des3_encrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ mit_des3_key_schedule schedule;
+ krb5_error_code err;
+
+ err = validate_and_schedule_iov(key, ivec, data, num_data, &schedule);
+ if (err)
+ return err;
+
+ /* this has a return value, but the code always returns zero */
+ krb5int_des3_cbc_encrypt_iov(data, num_data,
+ schedule[0], schedule[1], schedule[2],
+ ivec != NULL ? (unsigned char *) ivec->data : NULL);
+
+ zap(schedule, sizeof(schedule));
+
+ return(0);
+}
+
+static krb5_error_code
+k5_des3_decrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ mit_des3_key_schedule schedule;
+ krb5_error_code err;
+
+ err = validate_and_schedule_iov(key, ivec, data, num_data, &schedule);
+ if (err)
+ return err;
+
+ /* this has a return value, but the code always returns zero */
+ krb5int_des3_cbc_decrypt_iov(data, num_data,
+ schedule[0], schedule[1], schedule[2],
+ ivec != NULL ? (unsigned char *) ivec->data : NULL);
+
+ zap(schedule, sizeof(schedule));
+
+ return(0);
+}
+
+const struct krb5_enc_provider krb5int_enc_des3 = {
+ 8,
+ 21, 24,
+ k5_des3_encrypt,
+ k5_des3_decrypt,
+ k5_des3_make_key,
+ krb5int_des_init_state,
+ krb5int_default_free_state,
+ k5_des3_encrypt_iov,
+ k5_des3_decrypt_iov
+};
+
diff --git a/src/lib/crypto/krb/enc_provider/enc_provider.h b/src/lib/crypto/krb/enc_provider/enc_provider.h
new file mode 100644
index 0000000..92022b3
--- /dev/null
+++ b/src/lib/crypto/krb/enc_provider/enc_provider.h
@@ -0,0 +1,36 @@
+/*
+ * 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"
+
+extern const struct krb5_enc_provider krb5int_enc_des;
+extern const struct krb5_enc_provider krb5int_enc_des3;
+extern const struct krb5_enc_provider krb5int_enc_arcfour;
+extern const struct krb5_enc_provider krb5int_enc_aes128;
+extern const struct krb5_enc_provider krb5int_enc_aes256;
+extern const struct krb5_enc_provider krb5int_enc_aes128_ctr;
+extern const struct krb5_enc_provider krb5int_enc_aes256_ctr;
+
diff --git a/src/lib/crypto/krb/enc_provider/rc4.c b/src/lib/crypto/krb/enc_provider/rc4.c
new file mode 100644
index 0000000..b950a60
--- /dev/null
+++ b/src/lib/crypto/krb/enc_provider/rc4.c
@@ -0,0 +1,271 @@
+/* arcfour.c
+ *
+ * Copyright (c) 2000 by Computer Science Laboratory,
+ * Rensselaer Polytechnic Institute
+ *
+ * #include STD_DISCLAIMER
+ */
+
+#include "k5-int.h"
+#include "arcfour-int.h"
+#include "enc_provider.h"
+#include "../aead.h"
+/* gets the next byte from the PRNG */
+#if ((__GNUC__ >= 2) )
+static __inline__ unsigned int k5_arcfour_byte(ArcfourContext *);
+#else
+static unsigned int k5_arcfour_byte(ArcfourContext *);
+#endif /* gcc inlines*/
+
+/* Initializes the context and sets the key. */
+static krb5_error_code k5_arcfour_init(ArcfourContext *ctx, const unsigned char *key,
+ unsigned int keylen);
+
+/* Encrypts/decrypts data. */
+static void k5_arcfour_crypt(ArcfourContext *ctx, unsigned char *dest,
+ const unsigned char *src, unsigned int len);
+
+/* Interface layer to kerb5 crypto layer */
+static krb5_error_code
+k5_arcfour_docrypt(const krb5_keyblock *, const krb5_data *,
+ const krb5_data *, krb5_data *);
+
+/* from a random bitstrem, construct a key */
+static krb5_error_code
+k5_arcfour_make_key(const krb5_data *, krb5_keyblock *);
+
+static const unsigned char arcfour_weakkey1[] = {0x00, 0x00, 0xfd};
+static const unsigned char arcfour_weakkey2[] = {0x03, 0xfd, 0xfc};
+static const struct {
+ size_t length;
+ const unsigned char *data;
+} arcfour_weakkeys[] = {
+ { sizeof (arcfour_weakkey1), arcfour_weakkey1},
+ { sizeof (arcfour_weakkey2), arcfour_weakkey2},
+};
+
+static inline unsigned int k5_arcfour_byte(ArcfourContext * ctx)
+{
+ unsigned int x;
+ unsigned int y;
+ unsigned int sx, sy;
+ unsigned char *state;
+
+ state = ctx->state;
+ x = (ctx->x + 1) & 0xff;
+ sx = state[x];
+ y = (sx + ctx->y) & 0xff;
+ sy = state[y];
+ ctx->x = x;
+ ctx->y = y;
+ state[y] = sx;
+ state[x] = sy;
+ return state[(sx + sy) & 0xff];
+}
+
+static void k5_arcfour_crypt(ArcfourContext *ctx, unsigned char *dest,
+ const unsigned char *src, unsigned int len)
+{
+ unsigned int i;
+ for (i = 0; i < len; i++)
+ dest[i] = src[i] ^ k5_arcfour_byte(ctx);
+}
+
+
+static krb5_error_code
+k5_arcfour_init(ArcfourContext *ctx, const unsigned char *key,
+ unsigned int key_len)
+{
+ unsigned int t, u;
+ unsigned int keyindex;
+ unsigned int stateindex;
+ unsigned char* state;
+ unsigned int counter;
+
+ if (key_len != 16)
+ return KRB5_BAD_MSIZE; /*this is probably not the correct error code
+ to return */
+ for (counter=0;
+ counter < sizeof(arcfour_weakkeys)/sizeof(arcfour_weakkeys[0]);
+ counter++)
+ if (!memcmp(key, arcfour_weakkeys[counter].data,
+ arcfour_weakkeys[counter].length))
+ return KRB5DES_WEAK_KEY; /* most certainly not the correct error */
+
+ state = &ctx->state[0];
+ ctx->x = 0;
+ ctx->y = 0;
+ for (counter = 0; counter < 256; counter++)
+ state[counter] = counter;
+ keyindex = 0;
+ stateindex = 0;
+ for (counter = 0; counter < 256; counter++)
+ {
+ t = state[counter];
+ stateindex = (stateindex + key[keyindex] + t) & 0xff;
+ u = state[stateindex];
+ state[stateindex] = t;
+ state[counter] = u;
+ if (++keyindex >= key_len)
+ keyindex = 0;
+ }
+ return 0;
+}
+
+
+/* The workhorse of the arcfour system, this impliments the cipher */
+static krb5_error_code
+k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state,
+ const krb5_data *input, krb5_data *output)
+{
+ ArcfourContext *arcfour_ctx;
+ ArcFourCipherState *cipher_state;
+ int ret;
+
+ if (key->length != 16)
+ return(KRB5_BAD_KEYSIZE);
+ if (state && (state->length != sizeof (ArcFourCipherState)))
+ return(KRB5_BAD_MSIZE);
+ if (input->length != output->length)
+ return(KRB5_BAD_MSIZE);
+
+ if (state) {
+ cipher_state = (ArcFourCipherState *) state->data;
+ arcfour_ctx=&cipher_state->ctx;
+ if (cipher_state->initialized == 0) {
+ if ((ret=k5_arcfour_init(arcfour_ctx, key->contents, key->length))) {
+ return ret;
+ }
+ cipher_state->initialized = 1;
+ }
+ k5_arcfour_crypt(arcfour_ctx, (unsigned char *) output->data, (const unsigned char *) input->data, input->length);
+ }
+ else {
+ arcfour_ctx=malloc(sizeof (ArcfourContext));
+ if (arcfour_ctx == NULL)
+ return ENOMEM;
+ if ((ret=k5_arcfour_init(arcfour_ctx, key->contents, key->length))) {
+ free(arcfour_ctx);
+ return (ret);
+ }
+ k5_arcfour_crypt(arcfour_ctx, (unsigned char * ) output->data,
+ (const unsigned char * ) input->data, input->length);
+ memset(arcfour_ctx, 0, sizeof (ArcfourContext));
+ free(arcfour_ctx);
+ }
+
+ return 0;
+}
+
+/* In-place encryption */
+static krb5_error_code
+k5_arcfour_docrypt_iov(const krb5_keyblock *key,
+ const krb5_data *state,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ ArcfourContext *arcfour_ctx = NULL;
+ ArcFourCipherState *cipher_state = NULL;
+ krb5_error_code ret;
+ size_t i;
+
+ if (key->length != 16)
+ return KRB5_BAD_KEYSIZE;
+ if (state != NULL && (state->length != sizeof(ArcFourCipherState)))
+ return KRB5_BAD_MSIZE;
+
+ if (state != NULL) {
+ cipher_state = (ArcFourCipherState *)state->data;
+ arcfour_ctx = &cipher_state->ctx;
+ if (cipher_state->initialized == 0) {
+ ret = k5_arcfour_init(arcfour_ctx, key->contents, key->length);
+ if (ret != 0)
+ return ret;
+
+ cipher_state->initialized = 1;
+ }
+ } else {
+ arcfour_ctx = (ArcfourContext *)malloc(sizeof(ArcfourContext));
+ if (arcfour_ctx == NULL)
+ return ENOMEM;
+
+ ret = k5_arcfour_init(arcfour_ctx, key->contents, key->length);
+ if (ret != 0) {
+ free(arcfour_ctx);
+ return ret;
+ }
+ }
+
+ for (i = 0; i < num_data; i++) {
+ krb5_crypto_iov *iov = &data[i];
+
+ if (ENCRYPT_IOV(iov))
+ k5_arcfour_crypt(arcfour_ctx, (unsigned char *)iov->data.data,
+ (const unsigned char *)iov->data.data, iov->data.length);
+ }
+
+ if (state == NULL) {
+ memset(arcfour_ctx, 0, sizeof(ArcfourContext));
+ free(arcfour_ctx);
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+k5_arcfour_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+ if (key->length != 16)
+ return(KRB5_BAD_KEYSIZE);
+ if (randombits->length != 16)
+ return(KRB5_CRYPTO_INTERNAL);
+
+ key->magic = KV5M_KEYBLOCK;
+ key->length = 16;
+
+ memcpy(key->contents, randombits->data, randombits->length);
+
+ return(0);
+}
+
+static krb5_error_code
+k5_arcfour_init_state (const krb5_keyblock *key,
+ krb5_keyusage keyusage, krb5_data *new_state)
+{
+ /* Note that we can't actually set up the state here because the key
+ * will change between now and when encrypt is called
+ * because it is data dependent. Yeah, this has strange
+ * properties. --SDH
+ */
+ new_state->length = sizeof (ArcFourCipherState);
+ new_state->data = malloc (new_state->length);
+ if (new_state->data) {
+ memset (new_state->data, 0 , new_state->length);
+ /* That will set initialized to zero*/
+ }else {
+ return (ENOMEM);
+ }
+ return 0;
+}
+
+/* Since the arcfour cipher is identical going forwards and backwards,
+ we just call "docrypt" directly
+*/
+const struct krb5_enc_provider krb5int_enc_arcfour = {
+ /* This seems to work... although I am not sure what the
+ implications are in other places in the kerberos library */
+ 1,
+ /* Keysize is arbitrary in arcfour, but the constraints of the
+ system, and to attempt to work with the MSFT system forces us
+ to 16byte/128bit. Since there is no parity in the key, the
+ byte and length are the same. */
+ 16, 16,
+ k5_arcfour_docrypt,
+ k5_arcfour_docrypt,
+ k5_arcfour_make_key,
+ k5_arcfour_init_state, /*xxx not implemented yet*/
+ krb5int_default_free_state,
+ k5_arcfour_docrypt_iov,
+ k5_arcfour_docrypt_iov
+};
+