aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/crypto/krb
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
committerCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
commit33a9b234e7087f573ef08cd7318c6497ba08b439 (patch)
treed0ea40ad3bf5463a3c55795977c71bcb7d781b4b /src/lib/crypto/krb
downloadsrc-33a9b234e7087f573ef08cd7318c6497ba08b439.tar.gz
src-33a9b234e7087f573ef08cd7318c6497ba08b439.zip
Import MIT KRB5 1.15.1, which will gracefully replace KTH Heimdal.vendor/krb5/1.15.1
The tarball used in this import is the same tarball used in ports/krb5-115 r435378. Obtained from: http://web.mit.edu/kerberos/dist/ Thanks to: pfg (for all your tireless behind-the-scenes effort)
Notes
Notes: svn path=/vendor-crypto/krb5/dist/; revision=320790 svn path=/vendor-crypto/krb5/1.15.1/; revision=320791; tag=vendor/krb5/1.15.1
Diffstat (limited to 'src/lib/crypto/krb')
-rw-r--r--src/lib/crypto/krb/Makefile.in227
-rw-r--r--src/lib/crypto/krb/aead.c223
-rw-r--r--src/lib/crypto/krb/block_size.c42
-rw-r--r--src/lib/crypto/krb/cf2.c176
-rw-r--r--src/lib/crypto/krb/checksum_cbc.c41
-rw-r--r--src/lib/crypto/krb/checksum_confounder.c159
-rw-r--r--src/lib/crypto/krb/checksum_dk_cmac.c59
-rw-r--r--src/lib/crypto/krb/checksum_dk_hmac.c59
-rw-r--r--src/lib/crypto/krb/checksum_etm.c65
-rw-r--r--src/lib/crypto/krb/checksum_hmac_md5.c94
-rw-r--r--src/lib/crypto/krb/checksum_length.c42
-rw-r--r--src/lib/crypto/krb/checksum_unkeyed.c36
-rw-r--r--src/lib/crypto/krb/cksumtype_to_string.c42
-rw-r--r--src/lib/crypto/krb/cksumtypes.c130
-rw-r--r--src/lib/crypto/krb/cmac.c200
-rw-r--r--src/lib/crypto/krb/coll_proof_cksum.c37
-rw-r--r--src/lib/crypto/krb/combine_keys.c230
-rw-r--r--src/lib/crypto/krb/crc32.c165
-rw-r--r--src/lib/crypto/krb/crypto_int.h668
-rw-r--r--src/lib/crypto/krb/crypto_length.c125
-rw-r--r--src/lib/crypto/krb/crypto_libinit.c35
-rw-r--r--src/lib/crypto/krb/decrypt.c101
-rw-r--r--src/lib/crypto/krb/decrypt_iov.c64
-rw-r--r--src/lib/crypto/krb/default_state.c54
-rw-r--r--src/lib/crypto/krb/deps783
-rw-r--r--src/lib/crypto/krb/derive.c354
-rw-r--r--src/lib/crypto/krb/enc_dk_cmac.c182
-rw-r--r--src/lib/crypto/krb/enc_dk_hmac.c269
-rw-r--r--src/lib/crypto/krb/enc_etm.c257
-rw-r--r--src/lib/crypto/krb/enc_old.c181
-rw-r--r--src/lib/crypto/krb/enc_raw.c109
-rw-r--r--src/lib/crypto/krb/enc_rc4.c347
-rw-r--r--src/lib/crypto/krb/encrypt.c94
-rw-r--r--src/lib/crypto/krb/encrypt_iov.c58
-rw-r--r--src/lib/crypto/krb/encrypt_length.c47
-rw-r--r--src/lib/crypto/krb/enctype_util.c133
-rw-r--r--src/lib/crypto/krb/etypes.c194
-rw-r--r--src/lib/crypto/krb/key.c110
-rw-r--r--src/lib/crypto/krb/keyblocks.c108
-rw-r--r--src/lib/crypto/krb/keyed_checksum_types.c82
-rw-r--r--src/lib/crypto/krb/keyed_cksum.c39
-rw-r--r--src/lib/crypto/krb/keylengths.c57
-rw-r--r--src/lib/crypto/krb/make_checksum.c99
-rw-r--r--src/lib/crypto/krb/make_checksum_iov.c94
-rw-r--r--src/lib/crypto/krb/make_random_key.c76
-rw-r--r--src/lib/crypto/krb/mandatory_sumtype.c39
-rw-r--r--src/lib/crypto/krb/nfold.c127
-rw-r--r--src/lib/crypto/krb/old_api_glue.c390
-rw-r--r--src/lib/crypto/krb/prf.c84
-rw-r--r--src/lib/crypto/krb/prf_aes2.c42
-rw-r--r--src/lib/crypto/krb/prf_cmac.c58
-rw-r--r--src/lib/crypto/krb/prf_des.c47
-rw-r--r--src/lib/crypto/krb/prf_dk.c70
-rw-r--r--src/lib/crypto/krb/prf_rc4.c39
-rw-r--r--src/lib/crypto/krb/prng.c134
-rw-r--r--src/lib/crypto/krb/prng_device.c99
-rw-r--r--src/lib/crypto/krb/prng_fortuna.c470
-rw-r--r--src/lib/crypto/krb/prng_os.c72
-rw-r--r--src/lib/crypto/krb/random_to_key.c118
-rw-r--r--src/lib/crypto/krb/s2k_des.c691
-rw-r--r--src/lib/crypto/krb/s2k_pbkdf2.c216
-rw-r--r--src/lib/crypto/krb/s2k_rc4.c37
-rw-r--r--src/lib/crypto/krb/state.c60
-rw-r--r--src/lib/crypto/krb/string_to_cksumtype.c56
-rw-r--r--src/lib/crypto/krb/string_to_key.c74
-rw-r--r--src/lib/crypto/krb/t_fortuna.c179
-rw-r--r--src/lib/crypto/krb/t_fortuna.expected9
-rw-r--r--src/lib/crypto/krb/valid_cksumtype.c39
-rw-r--r--src/lib/crypto/krb/verify_checksum.c98
-rw-r--r--src/lib/crypto/krb/verify_checksum_iov.c101
70 files changed, 10096 insertions, 0 deletions
diff --git a/src/lib/crypto/krb/Makefile.in b/src/lib/crypto/krb/Makefile.in
new file mode 100644
index 000000000000..c5660c5fe1fa
--- /dev/null
+++ b/src/lib/crypto/krb/Makefile.in
@@ -0,0 +1,227 @@
+mydir=lib$(S)crypto$(S)krb
+BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/../$(CRYPTO_IMPL)
+
+##DOS##BUILDTOP = ..\..\..
+##DOS##PREFIXDIR = krb
+##DOS##OBJFILE = ..\$(OUTPRE)krb.lst
+
+STLIBOBJS=\
+ aead.o \
+ block_size.o \
+ cf2.o \
+ checksum_cbc.o \
+ checksum_confounder.o \
+ checksum_dk_cmac.o \
+ checksum_dk_hmac.o \
+ checksum_etm.o \
+ checksum_hmac_md5.o \
+ checksum_unkeyed.o \
+ checksum_length.o \
+ cksumtype_to_string.o \
+ cksumtypes.o \
+ cmac.o \
+ coll_proof_cksum.o \
+ combine_keys.o \
+ crc32.o \
+ crypto_length.o \
+ crypto_libinit.o \
+ default_state.o \
+ decrypt.o \
+ decrypt_iov.o \
+ derive.o \
+ encrypt.o \
+ encrypt_iov.o \
+ encrypt_length.o \
+ enctype_util.o \
+ enc_dk_cmac.o \
+ enc_dk_hmac.o \
+ enc_etm.o \
+ enc_old.o \
+ enc_raw.o \
+ enc_rc4.o \
+ etypes.o \
+ key.o \
+ keyblocks.o \
+ keyed_cksum.o \
+ keyed_checksum_types.o \
+ keylengths.o \
+ make_checksum.o \
+ make_checksum_iov.o \
+ make_random_key.o \
+ mandatory_sumtype.o \
+ nfold.o \
+ old_api_glue.o \
+ prf.o \
+ prf_aes2.o \
+ prf_cmac.o \
+ prf_des.o \
+ prf_dk.o \
+ prf_rc4.o \
+ prng.o \
+ prng_$(PRNG_ALG).o \
+ random_to_key.o \
+ s2k_des.o \
+ s2k_pbkdf2.o \
+ s2k_rc4.o \
+ state.o \
+ string_to_cksumtype.o \
+ string_to_key.o \
+ valid_cksumtype.o \
+ verify_checksum.o \
+ verify_checksum_iov.o
+
+OBJS=\
+ $(OUTPRE)aead.$(OBJEXT) \
+ $(OUTPRE)block_size.$(OBJEXT) \
+ $(OUTPRE)cf2.$(OBJEXT) \
+ $(OUTPRE)checksum_cbc.$(OBJEXT) \
+ $(OUTPRE)checksum_confounder.$(OBJEXT) \
+ $(OUTPRE)checksum_dk_cmac.$(OBJEXT) \
+ $(OUTPRE)checksum_dk_hmac.$(OBJEXT) \
+ $(OUTPRE)checksum_etm.$(OBJEXT) \
+ $(OUTPRE)checksum_hmac_md5.$(OBJEXT) \
+ $(OUTPRE)checksum_unkeyed.$(OBJEXT) \
+ $(OUTPRE)checksum_length.$(OBJEXT) \
+ $(OUTPRE)cksumtype_to_string.$(OBJEXT) \
+ $(OUTPRE)cksumtypes.$(OBJEXT) \
+ $(OUTPRE)cmac.$(OBJEXT) \
+ $(OUTPRE)coll_proof_cksum.$(OBJEXT) \
+ $(OUTPRE)combine_keys.$(OBJEXT) \
+ $(OUTPRE)crc32.$(OBJEXT) \
+ $(OUTPRE)crypto_length.$(OBJEXT) \
+ $(OUTPRE)crypto_libinit.$(OBJEXT) \
+ $(OUTPRE)default_state.$(OBJEXT) \
+ $(OUTPRE)decrypt.$(OBJEXT) \
+ $(OUTPRE)decrypt_iov.$(OBJEXT) \
+ $(OUTPRE)derive.$(OBJEXT) \
+ $(OUTPRE)encrypt.$(OBJEXT) \
+ $(OUTPRE)encrypt_iov.$(OBJEXT) \
+ $(OUTPRE)encrypt_length.$(OBJEXT) \
+ $(OUTPRE)enctype_util.$(OBJEXT) \
+ $(OUTPRE)enc_dk_cmac.$(OBJEXT) \
+ $(OUTPRE)enc_dk_hmac.$(OBJEXT) \
+ $(OUTPRE)enc_etm.$(OBJEXT) \
+ $(OUTPRE)enc_old.$(OBJEXT) \
+ $(OUTPRE)enc_raw.$(OBJEXT) \
+ $(OUTPRE)enc_rc4.$(OBJEXT) \
+ $(OUTPRE)etypes.$(OBJEXT) \
+ $(OUTPRE)key.$(OBJEXT) \
+ $(OUTPRE)keyblocks.$(OBJEXT) \
+ $(OUTPRE)keyed_cksum.$(OBJEXT) \
+ $(OUTPRE)keyed_checksum_types.$(OBJEXT) \
+ $(OUTPRE)keylengths.$(OBJEXT) \
+ $(OUTPRE)make_checksum.$(OBJEXT) \
+ $(OUTPRE)make_checksum_iov.$(OBJEXT) \
+ $(OUTPRE)make_random_key.$(OBJEXT) \
+ $(OUTPRE)mandatory_sumtype.$(OBJEXT) \
+ $(OUTPRE)nfold.$(OBJEXT) \
+ $(OUTPRE)old_api_glue.$(OBJEXT) \
+ $(OUTPRE)prf.$(OBJEXT) \
+ $(OUTPRE)prf_aes2.$(OBJEXT) \
+ $(OUTPRE)prf_cmac.$(OBJEXT) \
+ $(OUTPRE)prf_des.$(OBJEXT) \
+ $(OUTPRE)prf_dk.$(OBJEXT) \
+ $(OUTPRE)prf_rc4.$(OBJEXT) \
+ $(OUTPRE)prng.$(OBJEXT) \
+ $(OUTPRE)prng_$(PRNG_ALG).$(OBJEXT) \
+ $(OUTPRE)random_to_key.$(OBJEXT) \
+ $(OUTPRE)s2k_des.$(OBJEXT) \
+ $(OUTPRE)s2k_pbkdf2.$(OBJEXT) \
+ $(OUTPRE)s2k_rc4.$(OBJEXT) \
+ $(OUTPRE)state.$(OBJEXT) \
+ $(OUTPRE)string_to_cksumtype.$(OBJEXT) \
+ $(OUTPRE)string_to_key.$(OBJEXT) \
+ $(OUTPRE)valid_cksumtype.$(OBJEXT) \
+ $(OUTPRE)verify_checksum.$(OBJEXT) \
+ $(OUTPRE)verify_checksum_iov.$(OBJEXT)
+
+SRCS=\
+ $(srcdir)/aead.c \
+ $(srcdir)/block_size.c \
+ $(srcdir)/cf2.c \
+ $(srcdir)/checksum_cbc.c \
+ $(srcdir)/checksum_confounder.c \
+ $(srcdir)/checksum_dk_cmac.c \
+ $(srcdir)/checksum_dk_hmac.c \
+ $(srcdir)/checksum_etm.c \
+ $(srcdir)/checksum_hmac_md5.c \
+ $(srcdir)/checksum_unkeyed.c \
+ $(srcdir)/checksum_length.c \
+ $(srcdir)/cksumtype_to_string.c \
+ $(srcdir)/cksumtypes.c \
+ $(srcdir)/cmac.c \
+ $(srcdir)/coll_proof_cksum.c \
+ $(srcdir)/combine_keys.c \
+ $(srcdir)/crc32.c \
+ $(srcdir)/crypto_length.c \
+ $(srcdir)/crypto_libinit.c \
+ $(srcdir)/default_state.c \
+ $(srcdir)/decrypt.c \
+ $(srcdir)/decrypt_iov.c \
+ $(srcdir)/derive.c \
+ $(srcdir)/encrypt.c \
+ $(srcdir)/encrypt_iov.c \
+ $(srcdir)/encrypt_length.c \
+ $(srcdir)/enctype_util.c \
+ $(srcdir)/enc_dk_cmac.c \
+ $(srcdir)/enc_dk_hmac.c \
+ $(srcdir)/enc_etm.c \
+ $(srcdir)/enc_old.c \
+ $(srcdir)/enc_raw.c \
+ $(srcdir)/enc_rc4.c \
+ $(srcdir)/etypes.c \
+ $(srcdir)/key.c \
+ $(srcdir)/keyblocks.c \
+ $(srcdir)/keyed_cksum.c \
+ $(srcdir)/keyed_checksum_types.c\
+ $(srcdir)/keylengths.c \
+ $(srcdir)/make_checksum.c \
+ $(srcdir)/make_checksum_iov.c \
+ $(srcdir)/make_random_key.c \
+ $(srcdir)/mandatory_sumtype.c \
+ $(srcdir)/nfold.c \
+ $(srcdir)/old_api_glue.c \
+ $(srcdir)/prf.c \
+ $(srcdir)/prf_aes2.c \
+ $(srcdir)/prf_cmac.c \
+ $(srcdir)/prf_des.c \
+ $(srcdir)/prf_dk.c \
+ $(srcdir)/prf_rc4.c \
+ $(srcdir)/prng.c \
+ $(srcdir)/prng_$(PRNG_ALG).c \
+ $(srcdir)/cf2.c \
+ $(srcdir)/random_to_key.c \
+ $(srcdir)/s2k_des.c \
+ $(srcdir)/s2k_pbkdf2.c \
+ $(srcdir)/s2k_rc4.c \
+ $(srcdir)/state.c \
+ $(srcdir)/string_to_cksumtype.c \
+ $(srcdir)/string_to_key.c \
+ $(srcdir)/t_fortuna.c \
+ $(srcdir)/valid_cksumtype.c \
+ $(srcdir)/verify_checksum.c \
+ $(srcdir)/verify_checksum_iov.c
+
+##DOS##LIBOBJS = $(OBJS)
+
+all-unix: all-libobjs
+includes: depend
+
+depend: $(SRCS)
+
+check-unix: t_fortuna
+ if [ $(PRNG_ALG) = fortuna ]; then \
+ $(RUN_TEST) ./t_fortuna > t_fortuna.output; \
+ cmp t_fortuna.output $(srcdir)/t_fortuna.expected; \
+ fi
+
+t_fortuna: t_fortuna.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB)
+ $(CC_LINK) -o $@ t_fortuna.o $(K5CRYPTO_LIB) $(SUPPORT_LIB) $(LIBS)
+
+clean-unix:: clean-libobjs
+ $(RM) t_fortuna.o t_fortuna t_fortuna.output
+
+@lib_frag@
+@libobj_frag@
+
diff --git a/src/lib/crypto/krb/aead.c b/src/lib/crypto/krb/aead.c
new file mode 100644
index 000000000000..9d4e206ab77c
--- /dev/null
+++ b/src/lib/crypto/krb/aead.c
@@ -0,0 +1,223 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/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 "crypto_int.h"
+
+krb5_crypto_iov *
+krb5int_c_locate_iov(krb5_crypto_iov *data, size_t num_data,
+ krb5_cryptotype type)
+{
+ size_t i;
+ krb5_crypto_iov *iov = NULL;
+
+ if (data == NULL)
+ return NULL;
+
+ for (i = 0; i < num_data; i++) {
+ if (data[i].flags == type) {
+ if (iov == NULL)
+ iov = &data[i];
+ else
+ return NULL; /* can't appear twice */
+ }
+ }
+
+ return iov;
+}
+
+krb5_error_code
+krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage keyusage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ krb5_error_code ret;
+ unsigned int header_len, trailer_len;
+ krb5_crypto_iov *iov;
+ krb5_crypto_iov *stream;
+ size_t i, j;
+ int got_data = 0;
+
+ stream = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_STREAM);
+ assert(stream != NULL);
+
+ header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER);
+ trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+
+ if (stream->data.length < header_len + trailer_len)
+ return KRB5_BAD_MSIZE;
+
+ iov = calloc(num_data + 2, sizeof(krb5_crypto_iov));
+ if (iov == NULL)
+ return ENOMEM;
+
+ i = 0;
+
+ iov[i].flags = KRB5_CRYPTO_TYPE_HEADER; /* takes place of STREAM */
+ iov[i].data = make_data(stream->data.data, header_len);
+ i++;
+
+ for (j = 0; j < num_data; j++) {
+ if (data[j].flags == KRB5_CRYPTO_TYPE_DATA) {
+ if (got_data) {
+ free(iov);
+ return KRB5_BAD_MSIZE;
+ }
+
+ got_data++;
+
+ data[j].data.data = stream->data.data + header_len;
+ data[j].data.length = stream->data.length - header_len
+ - trailer_len;
+ }
+ if (data[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY ||
+ data[j].flags == KRB5_CRYPTO_TYPE_DATA)
+ iov[i++] = data[j];
+ }
+
+ /* Use empty padding since tokens don't indicate the padding length. */
+ iov[i].flags = KRB5_CRYPTO_TYPE_PADDING;
+ iov[i].data = empty_data();
+ i++;
+
+ iov[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
+ iov[i].data = make_data(stream->data.data + stream->data.length -
+ trailer_len, trailer_len);
+ i++;
+
+ assert(i <= num_data + 2);
+
+ ret = ktp->decrypt(ktp, key, keyusage, ivec, iov, i);
+ free(iov);
+ return ret;
+}
+
+unsigned int
+krb5int_c_padding_length(const struct krb5_keytypes *ktp, size_t data_length)
+{
+ unsigned int header, padding;
+
+ /*
+ * Add in the header length since the header is encrypted along with the
+ * data. (arcfour violates this assumption since not all of the header is
+ * encrypted, but that's okay since it has no padding. If there is ever an
+ * enctype using a similar token format and a block cipher, we will have to
+ * move this logic into an enctype-dependent function.)
+ */
+ header = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER);
+ data_length += header;
+
+ padding = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING);
+ if (padding == 0 || (data_length % padding) == 0)
+ return 0;
+ else
+ return padding - (data_length % padding);
+}
+
+/* Return the next iov (starting from ind) which cursor should process, or
+ * cursor->iov_count if there are none remaining. */
+static size_t
+next_iov_to_process(struct iov_cursor *cursor, size_t ind)
+{
+ const krb5_crypto_iov *iov;
+
+ for (; ind < cursor->iov_count; ind++) {
+ iov = &cursor->iov[ind];
+ if (cursor->signing ? SIGN_IOV(iov) : ENCRYPT_IOV(iov))
+ break;
+ }
+ return ind;
+}
+
+void
+k5_iov_cursor_init(struct iov_cursor *cursor, const krb5_crypto_iov *iov,
+ size_t count, size_t block_size, krb5_boolean signing)
+{
+ cursor->iov = iov;
+ cursor->iov_count = count;
+ cursor->block_size = block_size;
+ cursor->signing = signing;
+ cursor->in_iov = next_iov_to_process(cursor, 0);
+ cursor->out_iov = cursor->in_iov;
+ cursor->in_pos = cursor->out_pos = 0;
+}
+
+/* Fetch one block from cursor's input position. */
+krb5_boolean
+k5_iov_cursor_get(struct iov_cursor *cursor, unsigned char *block)
+{
+ size_t nbytes, bsz = cursor->block_size, remain = cursor->block_size;
+ const krb5_crypto_iov *iov;
+
+ remain = cursor->block_size;
+ while (remain > 0 && cursor->in_iov < cursor->iov_count) {
+ iov = &cursor->iov[cursor->in_iov];
+
+ nbytes = iov->data.length - cursor->in_pos;
+ if (nbytes > remain)
+ nbytes = remain;
+
+ memcpy(block + bsz - remain, iov->data.data + cursor->in_pos, nbytes);
+ cursor->in_pos += nbytes;
+ remain -= nbytes;
+
+ if (cursor->in_pos == iov->data.length) {
+ cursor->in_iov = next_iov_to_process(cursor, cursor->in_iov + 1);
+ cursor->in_pos = 0;
+ }
+ }
+
+ if (remain == bsz)
+ return FALSE;
+ if (remain > 0)
+ memset(block + bsz - remain, 0, remain);
+ return TRUE;
+}
+
+/* Write a block to a cursor's output position. */
+void
+k5_iov_cursor_put(struct iov_cursor *cursor, unsigned char *block)
+{
+ size_t nbytes, bsz = cursor->block_size, remain = cursor->block_size;
+ const krb5_crypto_iov *iov;
+
+ remain = cursor->block_size;
+ while (remain > 0 && cursor->out_iov < cursor->iov_count) {
+ iov = &cursor->iov[cursor->out_iov];
+
+ nbytes = iov->data.length - cursor->out_pos;
+ if (nbytes > remain)
+ nbytes = remain;
+
+ memcpy(iov->data.data + cursor->out_pos, block + bsz - remain, nbytes);
+ cursor->out_pos += nbytes;
+ remain -= nbytes;
+
+ if (cursor->out_pos == iov->data.length) {
+ cursor->out_iov = next_iov_to_process(cursor, cursor->out_iov + 1);
+ cursor->out_pos = 0;
+ }
+ }
+}
diff --git a/src/lib/crypto/krb/block_size.c b/src/lib/crypto/krb/block_size.c
new file mode 100644
index 000000000000..d50c94469b35
--- /dev/null
+++ b/src/lib/crypto/krb/block_size.c
@@ -0,0 +1,42 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_block_size(krb5_context context, krb5_enctype enctype,
+ size_t *blocksize)
+{
+ const struct krb5_keytypes *ktp;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ *blocksize = ktp->enc->block_size;
+
+ return 0;
+}
diff --git a/src/lib/crypto/krb/cf2.c b/src/lib/crypto/krb/cf2.c
new file mode 100644
index 000000000000..2ee5aebda3f5
--- /dev/null
+++ b/src/lib/crypto/krb/cf2.c
@@ -0,0 +1,176 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/cf2.c */
+/*
+ * Copyright (C) 2009, 2015 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.
+ */
+
+/*
+ * Implement KRB_FX_CF2 function per draft-ietf-krb-wg-preauth-framework-09.
+ * Take two keys and two pepper strings as input and return a combined key.
+ */
+
+#include "crypto_int.h"
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_prfplus(krb5_context context, const krb5_keyblock *k,
+ const krb5_data *input, krb5_data *output)
+{
+ krb5_error_code ret;
+ krb5_data prf_in = empty_data(), prf_out = empty_data();
+ size_t prflen, nblocks, i;
+
+ /* Calculate the number of PRF invocations we will need. */
+ ret = krb5_c_prf_length(context, k->enctype, &prflen);
+ if (ret)
+ return ret;
+ nblocks = (output->length + prflen - 1)/ prflen;
+ if (nblocks > 255)
+ return E2BIG;
+
+ /* Allocate PRF input and output buffers. */
+ ret = alloc_data(&prf_in, input->length + 1);
+ if (ret)
+ goto cleanup;
+ ret = alloc_data(&prf_out, prflen);
+ if (ret)
+ goto cleanup;
+
+ /* Concatenate PRF(k, 1||input) || PRF(k, 2||input) || ... to produce the
+ * desired number of bytes. */
+ memcpy(&prf_in.data[1], input->data, input->length);
+ for (i = 0; i < nblocks; i++) {
+ prf_in.data[0] = i + 1;
+ ret = krb5_c_prf(context, k, &prf_in, &prf_out);
+ if (ret)
+ goto cleanup;
+
+ memcpy(&output->data[i * prflen], prf_out.data,
+ MIN(prflen, output->length - i * prflen));
+ }
+
+cleanup:
+ zapfree(prf_out.data, prf_out.length);
+ zapfree(prf_in.data, prf_in.length);
+ return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_derive_prfplus(krb5_context context, const krb5_keyblock *k,
+ const krb5_data *input, krb5_enctype enctype,
+ krb5_keyblock **out)
+{
+ krb5_error_code ret;
+ const struct krb5_keytypes *ktp;
+ krb5_data rnd = empty_data();
+ krb5_keyblock *kb = NULL;
+
+ *out = NULL;
+
+ ktp = find_enctype((enctype == ENCTYPE_NULL) ? k->enctype : enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ /* Generate enough pseudo-random bytes for the random-to-key function. */
+ ret = alloc_data(&rnd, ktp->enc->keybytes);
+ if (ret)
+ goto cleanup;
+ ret = krb5_c_prfplus(context, k, input, &rnd);
+ if (ret)
+ goto cleanup;
+
+ /* Generate a key from the pseudo-random bytes. */
+ ret = krb5int_c_init_keyblock(context, ktp->etype, ktp->enc->keylength,
+ &kb);
+ if (ret)
+ goto cleanup;
+ ret = (*ktp->rand2key)(&rnd, kb);
+ if (ret)
+ goto cleanup;
+
+ *out = kb;
+ kb = NULL;
+
+cleanup:
+ zapfree(rnd.data, rnd.length);
+ krb5int_c_free_keyblock(context, kb);
+ return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_fx_cf2_simple(krb5_context context,
+ const krb5_keyblock *k1, const char *pepper1,
+ const krb5_keyblock *k2, const char *pepper2,
+ krb5_keyblock **out)
+{
+ krb5_error_code ret;
+ const struct krb5_keytypes *ktp = NULL;
+ const krb5_data pepper1_data = string2data((char *)pepper1);
+ const krb5_data pepper2_data = string2data((char *)pepper2);
+ krb5_data prf1 = empty_data(), prf2 = empty_data();
+ unsigned int i;
+ krb5_keyblock *kb = NULL;
+
+ *out = NULL;
+
+ ktp = find_enctype(k1->enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ /* Generate PRF+(k1, pepper1) and PRF+(k2, kepper2). */
+ ret = alloc_data(&prf1, ktp->enc->keybytes);
+ if (ret)
+ goto cleanup;
+ ret = krb5_c_prfplus(context, k1, &pepper1_data, &prf1);
+ if (ret)
+ goto cleanup;
+ ret = alloc_data(&prf2, ktp->enc->keybytes);
+ if (ret)
+ goto cleanup;
+ ret = krb5_c_prfplus(context, k2, &pepper2_data, &prf2);
+ if (ret)
+ goto cleanup;
+
+ /* Compute the XOR of the two PRF+ values and generate a key. */
+ for (i = 0; i < prf1.length; i++)
+ prf1.data[i] ^= prf2.data[i];
+ ret = krb5int_c_init_keyblock(context, ktp->etype, ktp->enc->keylength,
+ &kb);
+ if (ret)
+ goto cleanup;
+ ret = (*ktp->rand2key)(&prf1, kb);
+ if (ret)
+ goto cleanup;
+
+ *out = kb;
+ kb = NULL;
+
+cleanup:
+ zapfree(prf2.data, prf2.length);
+ zapfree(prf1.data, prf1.length);
+ krb5int_c_free_keyblock(context, kb);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/checksum_cbc.c b/src/lib/crypto/krb/checksum_cbc.c
new file mode 100644
index 000000000000..48afeb0e5cc6
--- /dev/null
+++ b/src/lib/crypto/krb/checksum_cbc.c
@@ -0,0 +1,41 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/checksum_cbc.c */
+/*
+ * Copyright (C) 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.
+ */
+
+/* CBC checksum, which computes the ivec resulting from CBC encryption of the
+ * input. */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_cbc_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output)
+{
+ if (ctp->enc->cbc_mac == NULL)
+ return KRB5_CRYPTO_INTERNAL;
+ return ctp->enc->cbc_mac(key, data, num_data, NULL, output);
+}
diff --git a/src/lib/crypto/krb/checksum_confounder.c b/src/lib/crypto/krb/checksum_confounder.c
new file mode 100644
index 000000000000..34941562c416
--- /dev/null
+++ b/src/lib/crypto/krb/checksum_confounder.c
@@ -0,0 +1,159 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/checksum_confounder.c */
+/*
+ * Copyright (C) 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.
+ */
+
+/*
+ * Confounder checksum implementation, using tokens of the form:
+ * enc(xorkey, confounder | hash(confounder | data))
+ * where xorkey is the key XOR'd with 0xf0 bytes.
+ */
+
+#include "crypto_int.h"
+
+/* Derive a key by XOR with 0xF0 bytes. */
+static krb5_error_code
+mk_xorkey(krb5_key origkey, krb5_key *xorkey)
+{
+ krb5_error_code retval = 0;
+ unsigned char *xorbytes;
+ krb5_keyblock xorkeyblock;
+ size_t i = 0;
+
+ xorbytes = k5memdup(origkey->keyblock.contents, origkey->keyblock.length,
+ &retval);
+ if (xorbytes == NULL)
+ return retval;
+ for (i = 0; i < origkey->keyblock.length; i++)
+ xorbytes[i] ^= 0xf0;
+
+ /* Do a shallow copy here. */
+ xorkeyblock = origkey->keyblock;
+ xorkeyblock.contents = xorbytes;
+
+ retval = krb5_k_create_key(0, &xorkeyblock, xorkey);
+ zapfree(xorbytes, origkey->keyblock.length);
+ return retval;
+}
+
+krb5_error_code
+krb5int_confounder_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output)
+{
+ krb5_error_code ret;
+ krb5_data conf, hashval;
+ krb5_key xorkey = NULL;
+ krb5_crypto_iov *hash_iov, iov;
+ size_t blocksize = ctp->enc->block_size, hashsize = ctp->hash->hashsize;
+
+ /* Partition the output buffer into confounder and hash. */
+ conf = make_data(output->data, blocksize);
+ hashval = make_data(output->data + blocksize, hashsize);
+
+ /* Create the confounder. */
+ ret = krb5_c_random_make_octets(NULL, &conf);
+ if (ret != 0)
+ return ret;
+
+ ret = mk_xorkey(key, &xorkey);
+ if (ret)
+ return ret;
+
+ /* Hash the confounder, then the input data. */
+ hash_iov = k5calloc(num_data + 1, sizeof(krb5_crypto_iov), &ret);
+ if (hash_iov == NULL)
+ goto cleanup;
+ hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ hash_iov[0].data = conf;
+ memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
+ ret = ctp->hash->hash(hash_iov, num_data + 1, &hashval);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Confounder and hash are in output buffer; encrypt them in place. */
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = *output;
+ ret = ctp->enc->encrypt(xorkey, NULL, &iov, 1);
+
+cleanup:
+ free(hash_iov);
+ krb5_k_free_key(NULL, xorkey);
+ return ret;
+}
+
+krb5_error_code krb5int_confounder_verify(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ const krb5_data *input,
+ krb5_boolean *valid)
+{
+ krb5_error_code ret;
+ unsigned char *plaintext = NULL;
+ krb5_key xorkey = NULL;
+ krb5_data computed = empty_data();
+ krb5_crypto_iov *hash_iov = NULL, iov;
+ size_t blocksize = ctp->enc->block_size, hashsize = ctp->hash->hashsize;
+
+ plaintext = k5memdup(input->data, input->length, &ret);
+ if (plaintext == NULL)
+ return ret;
+
+ ret = mk_xorkey(key, &xorkey);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Decrypt the input checksum. */
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = make_data(plaintext, input->length);
+ ret = ctp->enc->decrypt(xorkey, NULL, &iov, 1);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Hash the confounder, then the input data. */
+ hash_iov = k5calloc(num_data + 1, sizeof(krb5_crypto_iov), &ret);
+ if (hash_iov == NULL)
+ goto cleanup;
+ hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ hash_iov[0].data = make_data(plaintext, blocksize);
+ memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
+ ret = alloc_data(&computed, hashsize);
+ if (ret != 0)
+ goto cleanup;
+ ret = ctp->hash->hash(hash_iov, num_data + 1, &computed);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Compare the decrypted hash to the computed one. */
+ *valid = (k5_bcmp(plaintext + blocksize, computed.data, hashsize) == 0);
+
+cleanup:
+ zapfree(plaintext, input->length);
+ zapfree(computed.data, hashsize);
+ free(hash_iov);
+ krb5_k_free_key(NULL, xorkey);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/checksum_dk_cmac.c b/src/lib/crypto/krb/checksum_dk_cmac.c
new file mode 100644
index 000000000000..809f9d729b41
--- /dev/null
+++ b/src/lib/crypto/krb/checksum_dk_cmac.c
@@ -0,0 +1,59 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/checksum_dk_cmac.c */
+/*
+ * Copyright 2010 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "crypto_int.h"
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+krb5_error_code
+krb5int_dk_cmac_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output)
+{
+ const struct krb5_enc_provider *enc = ctp->enc;
+ krb5_error_code ret;
+ unsigned char constantdata[K5CLENGTH];
+ krb5_data datain;
+ krb5_key kc;
+
+ /* Derive the key. */
+ datain = make_data(constantdata, K5CLENGTH);
+ store_32_be(usage, constantdata);
+ constantdata[4] = (char) 0x99;
+ ret = krb5int_derive_key(enc, NULL, key, &kc, &datain,
+ DERIVE_SP800_108_CMAC);
+ if (ret != 0)
+ return ret;
+
+ /* Hash the data. */
+ ret = krb5int_cmac_checksum(enc, kc, data, num_data, output);
+ if (ret != 0)
+ memset(output->data, 0, output->length);
+
+ krb5_k_free_key(NULL, kc);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/checksum_dk_hmac.c b/src/lib/crypto/krb/checksum_dk_hmac.c
new file mode 100644
index 000000000000..64ab8993e838
--- /dev/null
+++ b/src/lib/crypto/krb/checksum_dk_hmac.c
@@ -0,0 +1,59 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+krb5_error_code
+krb5int_dk_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output)
+{
+ const struct krb5_enc_provider *enc = ctp->enc;
+ krb5_error_code ret;
+ unsigned char constantdata[K5CLENGTH];
+ krb5_data datain;
+ krb5_key kc;
+
+ /* Derive the key. */
+ datain = make_data(constantdata, K5CLENGTH);
+ store_32_be(usage, constantdata);
+ constantdata[4] = (char) 0x99;
+ ret = krb5int_derive_key(enc, NULL, key, &kc, &datain, DERIVE_RFC3961);
+ if (ret)
+ return ret;
+
+ /* Hash the data. */
+ ret = krb5int_hmac(ctp->hash, kc, data, num_data, output);
+ if (ret)
+ memset(output->data, 0, output->length);
+
+ krb5_k_free_key(NULL, kc);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/checksum_etm.c b/src/lib/crypto/krb/checksum_etm.c
new file mode 100644
index 000000000000..eaa85b2d507a
--- /dev/null
+++ b/src/lib/crypto/krb/checksum_etm.c
@@ -0,0 +1,65 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/checksum_etm.c - checksum for encrypt-then-mac enctypes */
+/*
+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_etm_checksum(const struct krb5_cksumtypes *ctp, krb5_key key,
+ krb5_keyusage usage, const krb5_crypto_iov *data,
+ size_t num_data, krb5_data *output)
+{
+ krb5_error_code ret;
+ uint8_t label[5];
+ krb5_data label_data = make_data(label, 5), kc = empty_data();
+ krb5_keyblock kb = { 0 };
+
+ /* Derive the checksum key. */
+ store_32_be(usage, label);
+ label[4] = 0x99;
+ label_data = make_data(label, 5);
+ ret = alloc_data(&kc, ctp->hash->hashsize / 2);
+ if (ret)
+ goto cleanup;
+ ret = krb5int_derive_random(ctp->enc, ctp->hash, key, &kc, &label_data,
+ DERIVE_SP800_108_HMAC);
+ if (ret)
+ goto cleanup;
+
+ /* Compute an HMAC with kc over the data. */
+ kb.length = kc.length;
+ kb.contents = (uint8_t *)kc.data;
+ ret = krb5int_hmac_keyblock(ctp->hash, &kb, data, num_data, output);
+
+cleanup:
+ zapfree(kc.data, kc.length);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/checksum_hmac_md5.c b/src/lib/crypto/krb/checksum_hmac_md5.c
new file mode 100644
index 000000000000..ec024f396613
--- /dev/null
+++ b/src/lib/crypto/krb/checksum_hmac_md5.c
@@ -0,0 +1,94 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/checksum_hmac_md5.c */
+/*
+ * Copyright (C) 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.
+ */
+
+/*
+ * Microsoft HMAC-MD5 and MD5-HMAC checksums (see RFC 4757):
+ * HMAC(KS, hash(msusage || input))
+ * KS is HMAC(key, "signaturekey\0") for HMAC-MD5, or just the key for
+ * MD5-HMAC.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code krb5int_hmacmd5_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ krb5_data *output)
+{
+ krb5_keyusage ms_usage;
+ krb5_error_code ret;
+ krb5_keyblock ks, *keyblock;
+ krb5_crypto_iov *hash_iov = NULL, iov;
+ krb5_data ds = empty_data(), hashval = empty_data();
+ char t[4];
+
+ if (key == NULL || key->keyblock.length > ctp->hash->blocksize)
+ return KRB5_BAD_ENCTYPE;
+ if (ctp->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) {
+ /* Compute HMAC(key, "signaturekey\0") to get the signing key ks. */
+ ret = alloc_data(&ds, ctp->hash->hashsize);
+ if (ret != 0)
+ goto cleanup;
+
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = make_data("signaturekey", 13);
+ ret = krb5int_hmac(ctp->hash, key, &iov, 1, &ds);
+ if (ret)
+ goto cleanup;
+ ks.length = ds.length;
+ ks.contents = (krb5_octet *) ds.data;
+ keyblock = &ks;
+ } else /* For md5-hmac, just use the key. */
+ keyblock = &key->keyblock;
+
+ /* Compute the MD5 value of the input. */
+ ms_usage = krb5int_arcfour_translate_usage(usage);
+ store_32_le(ms_usage, t);
+ hash_iov = k5calloc(num_data + 1, sizeof(krb5_crypto_iov), &ret);
+ if (hash_iov == NULL)
+ goto cleanup;
+ hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ hash_iov[0].data = make_data(t, 4);
+ memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov));
+ ret = alloc_data(&hashval, ctp->hash->hashsize);
+ if (ret != 0)
+ goto cleanup;
+ ret = ctp->hash->hash(hash_iov, num_data + 1, &hashval);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Compute HMAC(ks, md5value). */
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = hashval;
+ ret = krb5int_hmac_keyblock(ctp->hash, keyblock, &iov, 1, output);
+
+cleanup:
+ zapfree(ds.data, ds.length);
+ zapfree(hashval.data, hashval.length);
+ free(hash_iov);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/checksum_length.c b/src/lib/crypto/krb/checksum_length.c
new file mode 100644
index 000000000000..d4071e1046c7
--- /dev/null
+++ b/src/lib/crypto/krb/checksum_length.c
@@ -0,0 +1,42 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_checksum_length(krb5_context context, krb5_cksumtype cksumtype,
+ size_t *length)
+{
+ const struct krb5_cksumtypes *ctp;
+
+ ctp = find_cksumtype(cksumtype);
+ if (ctp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ *length = ctp->output_size;
+ return 0;
+}
diff --git a/src/lib/crypto/krb/checksum_unkeyed.c b/src/lib/crypto/krb/checksum_unkeyed.c
new file mode 100644
index 000000000000..ff4f2b46c006
--- /dev/null
+++ b/src/lib/crypto/krb/checksum_unkeyed.c
@@ -0,0 +1,36 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/checksum_unkeyed.c - Unkeyed checksum handler */
+/*
+ * Copyright (C) 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.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_unkeyed_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output)
+{
+ return ctp->hash->hash(data, num_data, output);
+}
diff --git a/src/lib/crypto/krb/cksumtype_to_string.c b/src/lib/crypto/krb/cksumtype_to_string.c
new file mode 100644
index 000000000000..758940a18027
--- /dev/null
+++ b/src/lib/crypto/krb/cksumtype_to_string.c
@@ -0,0 +1,42 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_cksumtype_to_string(krb5_cksumtype cksumtype, char *buffer, size_t buflen)
+{
+ const struct krb5_cksumtypes *ctp;
+
+ ctp = find_cksumtype(cksumtype);
+ if (ctp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ if (strlcpy(buffer, ctp->out_string, buflen) >= buflen)
+ return ENOMEM;
+ return 0;
+}
diff --git a/src/lib/crypto/krb/cksumtypes.c b/src/lib/crypto/krb/cksumtypes.c
new file mode 100644
index 000000000000..85967f9aa0ad
--- /dev/null
+++ b/src/lib/crypto/krb/cksumtypes.c
@@ -0,0 +1,130 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+const struct krb5_cksumtypes krb5int_cksumtypes_list[] = {
+ { CKSUMTYPE_CRC32,
+ "crc32", { 0 }, "CRC-32",
+ NULL, &krb5int_hash_crc32,
+ krb5int_unkeyed_checksum, NULL,
+ 4, 4, CKSUM_UNKEYED | CKSUM_NOT_COLL_PROOF },
+
+ { CKSUMTYPE_RSA_MD4,
+ "md4", { 0 }, "RSA-MD4",
+ NULL, &krb5int_hash_md4,
+ krb5int_unkeyed_checksum, NULL,
+ 16, 16, CKSUM_UNKEYED },
+
+ { CKSUMTYPE_RSA_MD4_DES,
+ "md4-des", { 0 }, "RSA-MD4 with DES cbc mode",
+ &krb5int_enc_des, &krb5int_hash_md4,
+ krb5int_confounder_checksum, krb5int_confounder_verify,
+ 24, 24, 0 },
+
+ { CKSUMTYPE_DESCBC,
+ "des-cbc", { 0 }, "DES cbc mode",
+ &krb5int_enc_des, NULL,
+ krb5int_cbc_checksum, NULL,
+ 8, 8, 0 },
+
+ { CKSUMTYPE_RSA_MD5,
+ "md5", { 0 }, "RSA-MD5",
+ NULL, &krb5int_hash_md5,
+ krb5int_unkeyed_checksum, NULL,
+ 16, 16, CKSUM_UNKEYED },
+
+ { CKSUMTYPE_RSA_MD5_DES,
+ "md5-des", { 0 }, "RSA-MD5 with DES cbc mode",
+ &krb5int_enc_des, &krb5int_hash_md5,
+ krb5int_confounder_checksum, krb5int_confounder_verify,
+ 24, 24, 0 },
+
+ { CKSUMTYPE_NIST_SHA,
+ "sha", { 0 }, "NIST-SHA",
+ NULL, &krb5int_hash_sha1,
+ krb5int_unkeyed_checksum, NULL,
+ 20, 20, CKSUM_UNKEYED },
+
+ { CKSUMTYPE_HMAC_SHA1_DES3,
+ "hmac-sha1-des3", { "hmac-sha1-des3-kd" }, "HMAC-SHA1 DES3 key",
+ &krb5int_enc_des3, &krb5int_hash_sha1,
+ krb5int_dk_checksum, NULL,
+ 20, 20, 0 },
+
+ { CKSUMTYPE_HMAC_MD5_ARCFOUR,
+ "hmac-md5-rc4", { "hmac-md5-enc", "hmac-md5-earcfour" },
+ "Microsoft HMAC MD5",
+ NULL, &krb5int_hash_md5,
+ krb5int_hmacmd5_checksum, NULL,
+ 16, 16, 0 },
+
+ { CKSUMTYPE_HMAC_SHA1_96_AES128,
+ "hmac-sha1-96-aes128", { 0 }, "HMAC-SHA1 AES128 key",
+ &krb5int_enc_aes128, &krb5int_hash_sha1,
+ krb5int_dk_checksum, NULL,
+ 20, 12, 0 },
+
+ { CKSUMTYPE_HMAC_SHA1_96_AES256,
+ "hmac-sha1-96-aes256", { 0 }, "HMAC-SHA1 AES256 key",
+ &krb5int_enc_aes256, &krb5int_hash_sha1,
+ krb5int_dk_checksum, NULL,
+ 20, 12, 0 },
+
+ { CKSUMTYPE_MD5_HMAC_ARCFOUR,
+ "md5-hmac-rc4", { 0 }, "Microsoft MD5 HMAC",
+ &krb5int_enc_arcfour, &krb5int_hash_md5,
+ krb5int_hmacmd5_checksum, NULL,
+ 16, 16, 0 },
+
+ { CKSUMTYPE_CMAC_CAMELLIA128,
+ "cmac-camellia128", { 0 }, "CMAC Camellia128 key",
+ &krb5int_enc_camellia128, NULL,
+ krb5int_dk_cmac_checksum, NULL,
+ 16, 16, 0 },
+
+ { CKSUMTYPE_CMAC_CAMELLIA256,
+ "cmac-camellia256", { 0 }, "CMAC Camellia256 key",
+ &krb5int_enc_camellia256, NULL,
+ krb5int_dk_cmac_checksum, NULL,
+ 16, 16, 0 },
+
+ { CKSUMTYPE_HMAC_SHA256_128_AES128,
+ "hmac-sha256-128-aes128", { 0 }, "HMAC-SHA256 AES128 key",
+ &krb5int_enc_aes128, &krb5int_hash_sha256,
+ krb5int_etm_checksum, NULL,
+ 32, 16, 0 },
+
+ { CKSUMTYPE_HMAC_SHA384_192_AES256,
+ "hmac-sha384-192-aes256", { 0 }, "HMAC-SHA384 AES256 key",
+ &krb5int_enc_aes256, &krb5int_hash_sha384,
+ krb5int_etm_checksum, NULL,
+ 48, 24, 0 },
+};
+
+const size_t krb5int_cksumtypes_length =
+ sizeof(krb5int_cksumtypes_list) / sizeof(struct krb5_cksumtypes);
diff --git a/src/lib/crypto/krb/cmac.c b/src/lib/crypto/krb/cmac.c
new file mode 100644
index 000000000000..67ac1a178dce
--- /dev/null
+++ b/src/lib/crypto/krb/cmac.c
@@ -0,0 +1,200 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/cmac.c */
+/*
+ * Copyright 2010 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "crypto_int.h"
+
+#define BLOCK_SIZE 16
+
+static unsigned char const_Rb[BLOCK_SIZE] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
+};
+
+static void
+xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
+{
+ int z;
+
+ for (z = 0; z < BLOCK_SIZE / 4; z++) {
+ unsigned char *aptr = &a[z * 4];
+ unsigned char *bptr = &b[z * 4];
+ unsigned char *outptr = &out[z * 4];
+
+ store_32_n(load_32_n(aptr) ^ load_32_n(bptr), outptr);
+ }
+}
+
+static void
+leftshift_onebit(unsigned char *input, unsigned char *output)
+{
+ int i;
+ unsigned char overflow = 0;
+
+ for (i = BLOCK_SIZE - 1; i >= 0; i--) {
+ output[i] = input[i] << 1;
+ output[i] |= overflow;
+ overflow = (input[i] & 0x80) ? 1 : 0;
+ }
+}
+
+/* Generate subkeys K1 and K2 as described in RFC 4493 figure 2.2. */
+static krb5_error_code
+generate_subkey(const struct krb5_enc_provider *enc,
+ krb5_key key,
+ unsigned char *K1,
+ unsigned char *K2)
+{
+ unsigned char L[BLOCK_SIZE];
+ unsigned char tmp[BLOCK_SIZE];
+ krb5_data d;
+ krb5_error_code ret;
+
+ /* L := encrypt(K, const_Zero) */
+ memset(L, 0, sizeof(L));
+ d = make_data(L, BLOCK_SIZE);
+ ret = encrypt_block(enc, key, &d);
+ if (ret != 0)
+ return ret;
+
+ /* K1 := (MSB(L) == 0) ? L << 1 : (L << 1) XOR const_Rb */
+ if ((L[0] & 0x80) == 0) {
+ leftshift_onebit(L, K1);
+ } else {
+ leftshift_onebit(L, tmp);
+ xor_128(tmp, const_Rb, K1);
+ }
+
+ /* K2 := (MSB(K1) == 0) ? K1 << 1 : (K1 << 1) XOR const_Rb */
+ if ((K1[0] & 0x80) == 0) {
+ leftshift_onebit(K1, K2);
+ } else {
+ leftshift_onebit(K1, tmp);
+ xor_128(tmp, const_Rb, K2);
+ }
+
+ return 0;
+}
+
+/* Pad out lastb with a 1 bit followed by 0 bits, placing the result in pad. */
+static void
+padding(unsigned char *lastb, unsigned char *pad, int length)
+{
+ int j;
+
+ /* original last block */
+ for (j = 0; j < BLOCK_SIZE; j++) {
+ if (j < length) {
+ pad[j] = lastb[j];
+ } else if (j == length) {
+ pad[j] = 0x80;
+ } else {
+ pad[j] = 0x00;
+ }
+ }
+}
+
+/*
+ * Implementation of CMAC algorithm. When used with AES, this function
+ * is compatible with RFC 4493 figure 2.3.
+ */
+krb5_error_code
+krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key,
+ const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output)
+{
+ unsigned char Y[BLOCK_SIZE], M_last[BLOCK_SIZE], padded[BLOCK_SIZE];
+ unsigned char K1[BLOCK_SIZE], K2[BLOCK_SIZE];
+ unsigned char input[BLOCK_SIZE];
+ unsigned int n, i, flag;
+ krb5_error_code ret;
+ struct iov_cursor cursor;
+ size_t length;
+ krb5_crypto_iov iov[1];
+ krb5_data d;
+
+ assert(enc->cbc_mac != NULL);
+
+ if (enc->block_size != BLOCK_SIZE)
+ return KRB5_BAD_MSIZE;
+
+ length = iov_total_length(data, num_data, TRUE);
+
+ /* Step 1. */
+ ret = generate_subkey(enc, key, K1, K2);
+ if (ret != 0)
+ return ret;
+
+ /* Step 2. */
+ n = (length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+ /* Step 3. */
+ if (n == 0) {
+ n = 1;
+ flag = 0;
+ } else {
+ flag = ((length % BLOCK_SIZE) == 0);
+ }
+
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[0].data = make_data(input, BLOCK_SIZE);
+
+ /* Step 5 (we'll do step 4 in a bit). */
+ memset(Y, 0, BLOCK_SIZE);
+ d = make_data(Y, BLOCK_SIZE);
+
+ /* Step 6 (all but last block). */
+ k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, TRUE);
+ for (i = 0; i < n - 1; i++) {
+ k5_iov_cursor_get(&cursor, input);
+
+ ret = enc->cbc_mac(key, iov, 1, &d, &d);
+ if (ret != 0)
+ return ret;
+ }
+
+ /* Step 4. */
+ k5_iov_cursor_get(&cursor, input);
+ if (flag) {
+ /* last block is complete block */
+ xor_128(input, K1, M_last);
+ } else {
+ padding(input, padded, length % BLOCK_SIZE);
+ xor_128(padded, K2, M_last);
+ }
+
+ /* Step 6 (last block). */
+ iov[0].data = make_data(M_last, BLOCK_SIZE);
+ ret = enc->cbc_mac(key, iov, 1, &d, &d);
+ if (ret != 0)
+ return ret;
+
+ assert(output->length >= d.length);
+
+ output->length = d.length;
+ memcpy(output->data, d.data, d.length);
+
+ return 0;
+}
diff --git a/src/lib/crypto/krb/coll_proof_cksum.c b/src/lib/crypto/krb/coll_proof_cksum.c
new file mode 100644
index 000000000000..13cb182aee83
--- /dev/null
+++ b/src/lib/crypto/krb/coll_proof_cksum.c
@@ -0,0 +1,37 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_boolean KRB5_CALLCONV
+krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype)
+{
+ const struct krb5_cksumtypes *ctp;
+
+ ctp = find_cksumtype(ctype);
+ return (ctp != NULL && !(ctp->flags & CKSUM_NOT_COLL_PROOF));
+}
diff --git a/src/lib/crypto/krb/combine_keys.c b/src/lib/crypto/krb/combine_keys.c
new file mode 100644
index 000000000000..90905c5ae2d8
--- /dev/null
+++ b/src/lib/crypto/krb/combine_keys.c
@@ -0,0 +1,230 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* Copyright (c) 2002 Naval Research Laboratory (NRL/CCS) */
+/*
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the software,
+ * derivative works or modified versions, and any portions thereof.
+ *
+ * NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
+ * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM THE USE OF THIS SOFTWARE.
+ */
+
+/*
+ * Key combination function.
+ *
+ * If Key1 and Key2 are two keys to be combined, the algorithm to combine
+ * them is as follows.
+ *
+ * Definitions:
+ *
+ * k-truncate is defined as truncating to the key size the input.
+ *
+ * DR is defined as the generate "random" data from a key
+ * (defined in crypto draft)
+ *
+ * DK is defined as the key derivation function (krb5int_derive_key())
+ *
+ * (note: | means "concatenate")
+ *
+ * Combine key algorithm:
+ *
+ * R1 = DR(Key1, n-fold(Key2)) [ Output is length of Key1 ]
+ * R2 = DR(Key2, n-fold(Key1)) [ Output is length of Key2 ]
+ *
+ * rnd = n-fold(R1 | R2) [ Note: output size of nfold must be appropriately
+ * sized for random-to-key function ]
+ * tkey = random-to-key(rnd)
+ * Combine-Key(Key1, Key2) = DK(tkey, CombineConstant)
+ *
+ * CombineConstant is defined as the byte string:
+ *
+ * { 0x63 0x6f 0x6d 0x62 0x69 0x6e 0x65 }, which corresponds to the
+ * ASCII encoding of the string "combine"
+ */
+
+#include "crypto_int.h"
+
+static krb5_error_code dr(const struct krb5_enc_provider *enc,
+ const krb5_keyblock *inkey, unsigned char *outdata,
+ const krb5_data *in_constant);
+
+/*
+ * We only support this combine_keys algorithm for des and 3des keys.
+ * Everything else should use the PRF defined in the crypto framework.
+ * We don't implement that yet.
+ */
+
+static krb5_boolean
+enctype_ok(krb5_enctype e)
+{
+ switch (e) {
+ case ENCTYPE_DES_CBC_CRC:
+ case ENCTYPE_DES_CBC_MD4:
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES3_CBC_SHA1:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+krb5_error_code
+krb5int_c_combine_keys(krb5_context context, krb5_keyblock *key1,
+ krb5_keyblock *key2, krb5_keyblock *outkey)
+{
+ unsigned char *r1 = NULL, *r2 = NULL, *combined = NULL, *rnd = NULL;
+ unsigned char *output = NULL;
+ size_t keybytes, keylength;
+ const struct krb5_enc_provider *enc;
+ krb5_data input, randbits;
+ krb5_keyblock tkeyblock;
+ krb5_key tkey = NULL;
+ krb5_error_code ret;
+ const struct krb5_keytypes *ktp;
+ krb5_boolean myalloc = FALSE;
+
+ if (!enctype_ok(key1->enctype) || !enctype_ok(key2->enctype))
+ return KRB5_CRYPTO_INTERNAL;
+
+ if (key1->length != key2->length || key1->enctype != key2->enctype)
+ return KRB5_CRYPTO_INTERNAL;
+
+ /* Find our encryption algorithm. */
+ ktp = find_enctype(key1->enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ enc = ktp->enc;
+
+ keybytes = enc->keybytes;
+ keylength = enc->keylength;
+
+ /* Allocate and set up buffers. */
+ r1 = k5alloc(keybytes, &ret);
+ if (ret)
+ goto cleanup;
+ r2 = k5alloc(keybytes, &ret);
+ if (ret)
+ goto cleanup;
+ rnd = k5alloc(keybytes, &ret);
+ if (ret)
+ goto cleanup;
+ combined = k5calloc(2, keybytes, &ret);
+ if (ret)
+ goto cleanup;
+ output = k5alloc(keylength, &ret);
+ if (ret)
+ goto cleanup;
+
+ /*
+ * Get R1 and R2 (by running the input keys through the DR algorithm.
+ * Note this is most of derive-key, but not all.
+ */
+
+ input.length = key2->length;
+ input.data = (char *) key2->contents;
+ ret = dr(enc, key1, r1, &input);
+ if (ret)
+ goto cleanup;
+
+ input.length = key1->length;
+ input.data = (char *) key1->contents;
+ ret = dr(enc, key2, r2, &input);
+ if (ret)
+ goto cleanup;
+
+ /*
+ * Concatenate the two keys together, and then run them through
+ * n-fold to reduce them to a length appropriate for the random-to-key
+ * operation. Note here that krb5int_nfold() takes sizes in bits, hence
+ * the multiply by 8.
+ */
+
+ memcpy(combined, r1, keybytes);
+ memcpy(combined + keybytes, r2, keybytes);
+
+ krb5int_nfold((keybytes * 2) * 8, combined, keybytes * 8, rnd);
+
+ /*
+ * Run the "random" bits through random-to-key to produce a encryption
+ * key.
+ */
+
+ randbits.length = keybytes;
+ randbits.data = (char *) rnd;
+ tkeyblock.length = keylength;
+ tkeyblock.contents = output;
+ tkeyblock.enctype = key1->enctype;
+
+ ret = (*ktp->rand2key)(&randbits, &tkeyblock);
+ if (ret)
+ goto cleanup;
+
+ ret = krb5_k_create_key(NULL, &tkeyblock, &tkey);
+ if (ret)
+ goto cleanup;
+
+ /*
+ * Run through derive-key one more time to produce the final key.
+ * Note that the input to derive-key is the ASCII string "combine".
+ */
+
+ input.length = 7;
+ input.data = "combine";
+
+ /*
+ * Just FYI: _if_ we have space here in the key, then simply use it
+ * without modification. But if the key is blank (no allocated storage)
+ * then allocate some memory for it. This allows programs to use one of
+ * the existing keys as the output key, _or_ pass in a blank keyblock
+ * for us to allocate. It's easier for us to allocate it since we already
+ * know the crypto library internals
+ */
+
+ if (outkey->length == 0 || outkey->contents == NULL) {
+ outkey->contents = k5alloc(keylength, &ret);
+ if (ret)
+ goto cleanup;
+ outkey->length = keylength;
+ outkey->enctype = key1->enctype;
+ myalloc = TRUE;
+ }
+
+ ret = krb5int_derive_keyblock(enc, NULL, tkey, outkey, &input,
+ DERIVE_RFC3961);
+ if (ret) {
+ if (myalloc) {
+ free(outkey->contents);
+ outkey->contents = NULL;
+ }
+ goto cleanup;
+ }
+
+cleanup:
+ zapfree(r1, keybytes);
+ zapfree(r2, keybytes);
+ zapfree(rnd, keybytes);
+ zapfree(combined, keybytes * 2);
+ zapfree(output, keylength);
+ krb5_k_free_key(NULL, tkey);
+ return ret;
+}
+
+/* Our DR function, a simple wrapper around krb5int_derive_random(). */
+static krb5_error_code
+dr(const struct krb5_enc_provider *enc, const krb5_keyblock *inkey,
+ unsigned char *out, const krb5_data *in_constant)
+{
+ krb5_data outdata = make_data(out, enc->keybytes);
+ krb5_key key = NULL;
+ krb5_error_code ret;
+
+ ret = krb5_k_create_key(NULL, inkey, &key);
+ if (ret != 0)
+ return ret;
+ ret = krb5int_derive_random(enc, NULL, key, &outdata, in_constant,
+ DERIVE_RFC3961);
+ krb5_k_free_key(NULL, key);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/crc32.c b/src/lib/crypto/krb/crc32.c
new file mode 100644
index 000000000000..d3b1b7a134d8
--- /dev/null
+++ b/src/lib/crypto/krb/crc32.c
@@ -0,0 +1,165 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/crc32.c */
+/*
+ * Copyright 1990, 2002 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+/*
+ * Copyright (C) 1986 Gary S. Brown. You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
+ */
+
+/*
+ *
+ * CRC-32/AUTODIN-II routines
+ */
+
+#include "crypto_int.h"
+
+/* First, the polynomial itself and its table of feedback terms. The */
+/* polynomial is */
+/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
+/* Note that we take it "backwards" and put the highest-order term in */
+/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
+/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
+/* the MSB being 1. */
+
+/* Note that the usual hardware shift register implementation, which */
+/* is what we're using (we're merely optimizing it by doing eight-bit */
+/* chunks at a time) shifts bits into the lowest-order term. In our */
+/* implementation, that means shifting towards the right. Why do we */
+/* do it this way? Because the calculated CRC must be transmitted in */
+/* order from highest-order term to lowest-order term. UARTs transmit */
+/* characters in order from LSB to MSB. By storing the CRC this way, */
+/* we hand it to the UART in the order low-byte to high-byte; the UART */
+/* sends each low-bit to hight-bit; and the result is transmission bit */
+/* by bit from highest- to lowest-order term without requiring any bit */
+/* shuffling on our part. Reception works similarly. */
+
+/* The feedback terms table consists of 256, 32-bit entries. Notes: */
+/* */
+/* 1. The table can be generated at runtime if desired; code to do so */
+/* is shown later. It might not be obvious, but the feedback */
+/* terms simply represent the results of eight shift/xor opera- */
+/* tions for all combinations of data and CRC register values. */
+/* */
+/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
+/* be they sixteen or thirty-two bits wide. You simply choose the */
+/* appropriate table. Alternatively, because the table can be */
+/* generated at runtime, you can start by generating the table for */
+/* the polynomial in question and use exactly the same "updcrc", */
+/* if your application needn't simultaneously handle two CRC */
+/* polynomials. (Note, however, that XMODEM is strange.) */
+/* */
+/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
+/* of course, 32-bit entries work OK if the high 16 bits are zero. */
+/* */
+/* 4. The values must be right-shifted by eight bits by the "updcrc" */
+/* logic; the shift must be unsigned (bring in zeroes). On some */
+/* hardware you could probably optimize the shift in assembler by */
+/* using byte-swap instructions. */
+
+static u_long const crc_table[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+void
+mit_crc32(krb5_pointer in, size_t in_length, unsigned long *cksum)
+{
+ register u_char *data;
+ register u_long c = *cksum;
+ register int idx;
+ size_t i;
+
+ data = (u_char *)in;
+ for (i = 0; i < in_length; i++) {
+ idx = (int) (data[i] ^ c);
+ idx &= 0xff;
+ c >>= 8;
+ c ^= crc_table[idx];
+ }
+
+ *cksum = c;
+}
diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h
new file mode 100644
index 000000000000..d75b49c693f0
--- /dev/null
+++ b/src/lib/crypto/krb/crypto_int.h
@@ -0,0 +1,668 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/crypto_int.h - Master libk5crypto internal header */
+/*
+ * Copyright (C) 2011 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/* This header is the entry point for libk5crypto sources, and also documents
+ * requirements for crypto modules and PRNG modules. */
+
+#ifndef CRYPTO_INT_H
+#define CRYPTO_INT_H
+
+#include <k5-int.h>
+
+/* Enc providers and hash providers specify well-known ciphers and hashes to be
+ * implemented by the crypto module. */
+
+struct krb5_enc_provider {
+ /* keybytes is the input size to make_key;
+ keylength is the output size */
+ size_t block_size, keybytes, keylength;
+
+ krb5_error_code (*encrypt)(krb5_key key, const krb5_data *cipher_state,
+ krb5_crypto_iov *data, size_t num_data);
+
+ krb5_error_code (*decrypt)(krb5_key key, const krb5_data *cipher_state,
+ krb5_crypto_iov *data, size_t num_data);
+
+ /* May be NULL if the cipher is not used for a cbc-mac checksum. */
+ krb5_error_code (*cbc_mac)(krb5_key key, const krb5_crypto_iov *data,
+ size_t num_data, const krb5_data *ivec,
+ krb5_data *output);
+
+ krb5_error_code (*init_state)(const krb5_keyblock *key,
+ krb5_keyusage keyusage,
+ krb5_data *out_state);
+ void (*free_state)(krb5_data *state);
+
+ /* May be NULL if there is no key-derived data cached. */
+ void (*key_cleanup)(krb5_key key);
+};
+
+struct krb5_hash_provider {
+ char hash_name[8];
+ size_t hashsize, blocksize;
+
+ krb5_error_code (*hash)(const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output);
+};
+
+/*** RFC 3961 enctypes table ***/
+
+#define MAX_ETYPE_ALIASES 2
+
+struct krb5_keytypes;
+
+typedef unsigned int (*crypto_length_func)(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type);
+
+typedef krb5_error_code (*crypt_func)(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage keyusage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data);
+
+typedef krb5_error_code (*str2key_func)(const struct krb5_keytypes *ktp,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *parm,
+ krb5_keyblock *key);
+
+typedef krb5_error_code (*rand2key_func)(const krb5_data *randombits,
+ krb5_keyblock *key);
+
+typedef krb5_error_code (*prf_func)(const struct krb5_keytypes *ktp,
+ krb5_key key,
+ const krb5_data *in, krb5_data *out);
+
+struct krb5_keytypes {
+ krb5_enctype etype;
+ char *name;
+ char *aliases[MAX_ETYPE_ALIASES];
+ char *out_string;
+ const struct krb5_enc_provider *enc;
+ const struct krb5_hash_provider *hash;
+ size_t prf_length;
+ crypto_length_func crypto_length;
+ crypt_func encrypt;
+ crypt_func decrypt;
+ str2key_func str2key;
+ rand2key_func rand2key;
+ prf_func prf;
+ krb5_cksumtype required_ctype;
+ krb5_flags flags;
+};
+
+#define ETYPE_WEAK 1
+
+extern const struct krb5_keytypes krb5int_enctypes_list[];
+extern const int krb5int_enctypes_length;
+
+/*** RFC 3961 checksum types table ***/
+
+struct krb5_cksumtypes;
+
+/*
+ * Compute a checksum over the header, data, padding, and sign-only fields of
+ * the iov array data (of size num_data). The output buffer will already be
+ * allocated with ctp->compute_size bytes available; the handler just needs to
+ * fill in the contents. If ctp->enc is not NULL, the handler can assume that
+ * key is a valid-length key of an enctype which uses that enc provider.
+ */
+typedef krb5_error_code (*checksum_func)(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ krb5_data *output);
+
+/*
+ * Verify a checksum over the header, data, padding, and sign-only fields of
+ * the iov array data (of size num_data), and store the boolean result in
+ * *valid. The handler can assume that hash has length ctp->output_size. If
+ * ctp->enc is not NULL, the handler can assume that key a valid-length key of
+ * an enctype which uses that enc provider.
+ */
+typedef krb5_error_code (*verify_func)(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ const krb5_data *input,
+ krb5_boolean *valid);
+
+struct krb5_cksumtypes {
+ krb5_cksumtype ctype;
+ char *name;
+ char *aliases[2];
+ char *out_string;
+ const struct krb5_enc_provider *enc;
+ const struct krb5_hash_provider *hash;
+ checksum_func checksum;
+ verify_func verify; /* NULL means recompute checksum and compare */
+ unsigned int compute_size; /* Allocation size for checksum computation */
+ unsigned int output_size; /* Possibly truncated output size */
+ krb5_flags flags;
+};
+
+#define CKSUM_UNKEYED 0x0001
+#define CKSUM_NOT_COLL_PROOF 0x0002
+
+extern const struct krb5_cksumtypes krb5int_cksumtypes_list[];
+extern const size_t krb5int_cksumtypes_length;
+
+/*** Prototypes for enctype table functions ***/
+
+/* Length */
+unsigned int krb5int_old_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type);
+unsigned int krb5int_raw_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type);
+unsigned int krb5int_arcfour_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type);
+unsigned int krb5int_dk_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type);
+unsigned int krb5int_aes_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type);
+unsigned int krb5int_camellia_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type);
+unsigned int krb5int_aes2_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type);
+
+/* Encrypt */
+krb5_error_code krb5int_old_encrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data);
+krb5_error_code krb5int_raw_encrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data);
+krb5_error_code krb5int_arcfour_encrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data);
+krb5_error_code krb5int_dk_encrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data);
+krb5_error_code krb5int_dk_cmac_encrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data);
+krb5_error_code krb5int_etm_encrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data);
+
+/* Decrypt */
+krb5_error_code krb5int_old_decrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data);
+krb5_error_code krb5int_raw_decrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data);
+krb5_error_code krb5int_arcfour_decrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data);
+krb5_error_code krb5int_dk_decrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data);
+krb5_error_code krb5int_dk_cmac_decrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data);
+krb5_error_code krb5int_etm_decrypt(const struct krb5_keytypes *ktp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data);
+
+/* String to key */
+krb5_error_code krb5int_des_string_to_key(const struct krb5_keytypes *ktp,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key);
+krb5_error_code krb5int_arcfour_string_to_key(const struct krb5_keytypes *ktp,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key);
+krb5_error_code krb5int_dk_string_to_key(const struct krb5_keytypes *enc,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key);
+krb5_error_code krb5int_aes_string_to_key(const struct krb5_keytypes *enc,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key);
+krb5_error_code krb5int_camellia_string_to_key(const struct krb5_keytypes *enc,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key);
+krb5_error_code krb5int_aes2_string_to_key(const struct krb5_keytypes *enc,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key);
+
+/* Random to key */
+krb5_error_code k5_rand2key_direct(const krb5_data *randombits,
+ krb5_keyblock *keyblock);
+krb5_error_code k5_rand2key_des(const krb5_data *randombits,
+ krb5_keyblock *keyblock);
+krb5_error_code k5_rand2key_des3(const krb5_data *randombits,
+ krb5_keyblock *keyblock);
+
+/* Pseudo-random function */
+krb5_error_code krb5int_des_prf(const struct krb5_keytypes *ktp,
+ krb5_key key, const krb5_data *in,
+ krb5_data *out);
+krb5_error_code krb5int_arcfour_prf(const struct krb5_keytypes *ktp,
+ krb5_key key, const krb5_data *in,
+ krb5_data *out);
+krb5_error_code krb5int_dk_prf(const struct krb5_keytypes *ktp, krb5_key key,
+ const krb5_data *in, krb5_data *out);
+krb5_error_code krb5int_dk_cmac_prf(const struct krb5_keytypes *ktp,
+ krb5_key key, const krb5_data *in,
+ krb5_data *out);
+krb5_error_code krb5int_aes2_prf(const struct krb5_keytypes *ktp, krb5_key key,
+ const krb5_data *in, krb5_data *out);
+
+/*** Prototypes for cksumtype handler functions ***/
+
+krb5_error_code krb5int_unkeyed_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ krb5_data *output);
+krb5_error_code krb5int_cbc_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ krb5_data *output);
+krb5_error_code krb5int_hmacmd5_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ krb5_data *output);
+krb5_error_code krb5int_dk_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data, krb5_data *output);
+krb5_error_code krb5int_dk_cmac_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data, krb5_data *output);
+krb5_error_code krb5int_confounder_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ krb5_data *output);
+krb5_error_code krb5int_confounder_verify(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ const krb5_data *input,
+ krb5_boolean *valid);
+krb5_error_code krb5int_etm_checksum(const struct krb5_cksumtypes *ctp,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data, krb5_data *output);
+
+/*** Key derivation functions ***/
+
+enum deriv_alg {
+ DERIVE_RFC3961, /* RFC 3961 section 5.1 */
+ DERIVE_SP800_108_CMAC, /* NIST SP 800-108 with CMAC as PRF */
+ DERIVE_SP800_108_HMAC /* NIST SP 800-108 with HMAC as PRF */
+};
+
+krb5_error_code krb5int_derive_keyblock(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_keyblock *outkey,
+ const krb5_data *in_constant,
+ enum deriv_alg alg);
+krb5_error_code krb5int_derive_key(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_key *outkey,
+ const krb5_data *in_constant,
+ enum deriv_alg alg);
+krb5_error_code krb5int_derive_random(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant,
+ enum deriv_alg alg);
+krb5_error_code
+k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *label, const krb5_data *context);
+
+/*** Miscellaneous prototypes ***/
+
+/* nfold algorithm from RFC 3961 */
+void krb5int_nfold(unsigned int inbits, const unsigned char *in,
+ unsigned int outbits, unsigned char *out);
+
+/* Compute a CMAC checksum over data. */
+krb5_error_code krb5int_cmac_checksum(const struct krb5_enc_provider *enc,
+ krb5_key key,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ krb5_data *output);
+
+/* Compute a CRC-32 checksum. c is in-out to allow chaining; init to 0. */
+#define CRC32_CKSUM_LENGTH 4
+void mit_crc32(krb5_pointer in, size_t in_length, unsigned long *c);
+
+/* Translate an RFC 3961 key usage to a Microsoft RC4 usage. */
+krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage);
+
+/* Ensure library initialization has occurred. */
+int krb5int_crypto_init(void);
+
+/* DES default state initialization handler (used by module enc providers). */
+krb5_error_code krb5int_des_init_state(const krb5_keyblock *key,
+ krb5_keyusage keyusage,
+ krb5_data *state_out);
+
+/* Default state cleanup handler (used by module enc providers). */
+void krb5int_default_free_state(krb5_data *state);
+
+/*** Input/output vector processing declarations **/
+
+#define ENCRYPT_CONF_IOV(_iov) ((_iov)->flags == KRB5_CRYPTO_TYPE_HEADER)
+
+#define ENCRYPT_DATA_IOV(_iov) ((_iov)->flags == KRB5_CRYPTO_TYPE_DATA || \
+ (_iov)->flags == KRB5_CRYPTO_TYPE_PADDING)
+
+#define ENCRYPT_IOV(_iov) (ENCRYPT_CONF_IOV(_iov) || ENCRYPT_DATA_IOV(_iov))
+
+#define SIGN_IOV(_iov) (ENCRYPT_IOV(_iov) || \
+ (_iov)->flags == KRB5_CRYPTO_TYPE_SIGN_ONLY )
+
+struct iov_cursor {
+ const krb5_crypto_iov *iov; /* iov array we are iterating over */
+ size_t iov_count; /* size of iov array */
+ size_t block_size; /* size of blocks we will be obtaining */
+ krb5_boolean signing; /* should we process SIGN_ONLY blocks */
+ size_t in_iov; /* read index into iov array */
+ size_t in_pos; /* read index into iov contents */
+ size_t out_iov; /* write index into iov array */
+ size_t out_pos; /* write index into iov contents */
+};
+
+krb5_crypto_iov *krb5int_c_locate_iov(krb5_crypto_iov *data, size_t num_data,
+ krb5_cryptotype type);
+
+krb5_error_code krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp,
+ krb5_key key,
+ krb5_keyusage keyusage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data);
+
+unsigned int krb5int_c_padding_length(const struct krb5_keytypes *ktp,
+ size_t data_length);
+
+void k5_iov_cursor_init(struct iov_cursor *cursor, const krb5_crypto_iov *iov,
+ size_t count, size_t block_size, krb5_boolean signing);
+
+krb5_boolean k5_iov_cursor_get(struct iov_cursor *cursor,
+ unsigned char *block);
+
+void k5_iov_cursor_put(struct iov_cursor *cursor, unsigned char *block);
+
+/*** Crypto module declarations ***/
+
+/* Modules must implement the k5_sha256() function prototyped in k5-int.h. */
+
+/* Modules must implement the following enc_providers and hash_providers: */
+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;
+extern const struct krb5_enc_provider krb5int_enc_camellia128;
+extern const struct krb5_enc_provider krb5int_enc_camellia256;
+
+extern const struct krb5_hash_provider krb5int_hash_crc32;
+extern const struct krb5_hash_provider krb5int_hash_md4;
+extern const struct krb5_hash_provider krb5int_hash_md5;
+extern const struct krb5_hash_provider krb5int_hash_sha1;
+extern const struct krb5_hash_provider krb5int_hash_sha256;
+extern const struct krb5_hash_provider krb5int_hash_sha384;
+
+/* Modules must implement the following functions. */
+
+/* Set the parity bits to the correct values in keybits. */
+void k5_des_fixup_key_parity(unsigned char *keybits);
+
+/* Return true if keybits is a weak or semi-weak DES key. */
+krb5_boolean k5_des_is_weak_key(unsigned char *keybits);
+
+/* Compute an HMAC using the provided hash function, key, and data, storing the
+ * result into output (caller-allocated). */
+krb5_error_code krb5int_hmac(const struct krb5_hash_provider *hash,
+ krb5_key key, const krb5_crypto_iov *data,
+ size_t num_data, krb5_data *output);
+
+/* As above, using a keyblock as the key input. */
+krb5_error_code krb5int_hmac_keyblock(const struct krb5_hash_provider *hash,
+ const krb5_keyblock *keyblock,
+ const krb5_crypto_iov *data,
+ size_t num_data, krb5_data *output);
+
+/*
+ * Compute the PBKDF2 (see RFC 2898) of password and salt, with the specified
+ * count, using HMAC with the specified hash as the pseudo-random function,
+ * storing the result into out (caller-allocated).
+ */
+krb5_error_code krb5int_pbkdf2_hmac(const struct krb5_hash_provider *hash,
+ const krb5_data *out, unsigned long count,
+ const krb5_data *password,
+ const krb5_data *salt);
+
+/* The following are used by test programs and are just handler functions from
+ * the AES and Camellia enc providers. */
+krb5_error_code krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data);
+krb5_error_code krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data);
+krb5_error_code krb5int_camellia_cbc_mac(krb5_key key,
+ const krb5_crypto_iov *data,
+ size_t num_data, const krb5_data *iv,
+ krb5_data *output);
+
+/* These can be used to safely set up and tear down module global state. */
+int krb5int_crypto_impl_init(void);
+void krb5int_crypto_impl_cleanup(void);
+
+/*
+ * Modules must provide a crypto_mod.h header at the top level. To work with
+ * the default PRNG module (prng_fortuna.c), crypto_mod.h must #define or
+ * prototype the following symbols:
+ *
+ * aes_ctx - Stack-allocatable type for an AES-128 or AES-256 key schedule
+ * krb5int_aes_enc_key(key, keybits, ctxptr) -- initialize a key schedule
+ * krb5int_aes_enc_blk(in, out, ctxptr) -- encrypt a block
+ * SHA256_CTX - Stack-allocatable type for a SHA-256 hash state
+ * k5_sha256_init(ctxptr) - Initialize a hash state
+ * k5_sha256_update(ctxptr, data, size) -- Hash some data
+ * k5_sha256_final(ctxptr, out) -- Finalize a state, writing hash into out
+ *
+ * These functions must never fail on valid inputs, and contexts must remain
+ * valid across forks. If the module cannot meet those constraints, then it
+ * should provide its own PRNG module and the build system should ensure that
+ * it is used.
+ *
+ * The function symbols named above are also in the library export list (so
+ * they can be used by the t_fortuna.c test code), so even if the module
+ * defines them away or doesn't work with Fortuna, the module must provide
+ * stubs; see stubs.c in the openssl module for examples.
+ */
+
+#include <crypto_mod.h>
+
+/*** PRNG module declarations ***/
+
+/*
+ * PRNG modules must implement the following APIs from krb5.h:
+ * krb5_c_random_add_entropy
+ * krb5_c_random_make_octets
+ * krb5_c_random_os_entropy
+ *
+ * PRNG modules should implement these functions. They are called from the
+ * crypto library init and cleanup functions, and can be used to setup and tear
+ * down static state without thread safety concerns.
+ */
+int k5_prng_init(void);
+void k5_prng_cleanup(void);
+
+/* Used by PRNG modules to gather OS entropy. Returns true on success. */
+krb5_boolean k5_get_os_entropy(unsigned char *buf, size_t len, int strong);
+
+/*** Inline helper functions ***/
+
+/* Find an enctype by number in the enctypes table. */
+static inline const struct krb5_keytypes *
+find_enctype(krb5_enctype enctype)
+{
+ int i;
+
+ for (i = 0; i < krb5int_enctypes_length; i++) {
+ if (krb5int_enctypes_list[i].etype == enctype)
+ break;
+ }
+
+ if (i == krb5int_enctypes_length)
+ return NULL;
+ return &krb5int_enctypes_list[i];
+}
+
+/* Find a checksum type by number in the cksumtypes table. */
+static inline const struct krb5_cksumtypes *
+find_cksumtype(krb5_cksumtype ctype)
+{
+ size_t i;
+
+ for (i = 0; i < krb5int_cksumtypes_length; i++) {
+ if (krb5int_cksumtypes_list[i].ctype == ctype)
+ break;
+ }
+
+ if (i == krb5int_cksumtypes_length)
+ return NULL;
+ return &krb5int_cksumtypes_list[i];
+}
+
+/* Verify that a key is appropriate for a checksum type. */
+static inline krb5_error_code
+verify_key(const struct krb5_cksumtypes *ctp, krb5_key key)
+{
+ const struct krb5_keytypes *ktp;
+
+ ktp = key ? find_enctype(key->keyblock.enctype) : NULL;
+ if (ctp->enc != NULL && (!ktp || ktp->enc != ctp->enc))
+ return KRB5_BAD_ENCTYPE;
+ if (key && (!ktp || key->keyblock.length != ktp->enc->keylength))
+ return KRB5_BAD_KEYSIZE;
+ return 0;
+}
+
+/* Encrypt one block of plaintext in place, for block ciphers. */
+static inline krb5_error_code
+encrypt_block(const struct krb5_enc_provider *enc, krb5_key key,
+ krb5_data *block)
+{
+ krb5_crypto_iov iov;
+
+ /* Verify that this is a block cipher and block is the right length. */
+ if (block->length != enc->block_size || enc->block_size == 1)
+ return EINVAL;
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = *block;
+ if (enc->cbc_mac != NULL) /* One-block cbc-mac with no ivec. */
+ return enc->cbc_mac(key, &iov, 1, NULL, block);
+ else /* Assume cbc-mode encrypt. */
+ return enc->encrypt(key, 0, &iov, 1);
+}
+
+/* Return the total length of the to-be-signed or to-be-encrypted buffers in an
+ * iov chain. */
+static inline size_t
+iov_total_length(const krb5_crypto_iov *data, size_t num_data,
+ krb5_boolean signing)
+{
+ size_t i, total = 0;
+
+ for (i = 0; i < num_data; i++) {
+ if (signing ? SIGN_IOV(&data[i]) : ENCRYPT_IOV(&data[i]))
+ total += data[i].data.length;
+ }
+ return total;
+}
+
+/*
+ * Return the number of contiguous blocks available within the current input
+ * IOV of the cursor c, so that the caller can do in-place encryption.
+ * Do not call if c might be exhausted.
+ */
+static inline size_t
+iov_cursor_contig_blocks(struct iov_cursor *c)
+{
+ return (c->iov[c->in_iov].data.length - c->in_pos) / c->block_size;
+}
+
+/* Return the current input pointer within the cursor c. Do not call if c
+ * might be exhausted. */
+static inline unsigned char *
+iov_cursor_ptr(struct iov_cursor *c)
+{
+ return (unsigned char *)&c->iov[c->in_iov].data.data[c->in_pos];
+}
+
+/*
+ * Advance the input and output pointers of c by nblocks blocks. nblocks must
+ * not be greater than the return value of iov_cursor_contig_blocks, and the
+ * input and output positions must be identical.
+ */
+static inline void
+iov_cursor_advance(struct iov_cursor *c, size_t nblocks)
+{
+ c->in_pos += nblocks * c->block_size;
+ c->out_pos += nblocks * c->block_size;
+}
+
+#endif /* CRYPTO_INT_H */
diff --git a/src/lib/crypto/krb/crypto_length.c b/src/lib/crypto/krb/crypto_length.c
new file mode 100644
index 000000000000..a621423a1e21
--- /dev/null
+++ b/src/lib/crypto/krb/crypto_length.c
@@ -0,0 +1,125 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/crypto_length.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 "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_crypto_length(krb5_context context, krb5_enctype enctype,
+ krb5_cryptotype type, unsigned int *size)
+{
+ const struct krb5_keytypes *ktp;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ switch (type) {
+ case KRB5_CRYPTO_TYPE_EMPTY:
+ case KRB5_CRYPTO_TYPE_SIGN_ONLY:
+ *size = 0;
+ break;
+ case KRB5_CRYPTO_TYPE_DATA:
+ *size = (unsigned int)~0; /* match Heimdal */
+ break;
+ case KRB5_CRYPTO_TYPE_HEADER:
+ case KRB5_CRYPTO_TYPE_PADDING:
+ case KRB5_CRYPTO_TYPE_TRAILER:
+ case KRB5_CRYPTO_TYPE_CHECKSUM:
+ *size = ktp->crypto_length(ktp, type);
+ break;
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_padding_length(krb5_context context, krb5_enctype enctype,
+ size_t data_length, unsigned int *pad_length)
+{
+ const struct krb5_keytypes *ktp;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ *pad_length = krb5int_c_padding_length(ktp, data_length);
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_crypto_length_iov(krb5_context context, krb5_enctype enctype,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ size_t i;
+ const struct krb5_keytypes *ktp;
+ unsigned int data_length = 0, pad_length;
+ krb5_crypto_iov *padding = NULL;
+
+ /*
+ * XXX need to rejig internal interface so we can accurately
+ * report variable header lengths.
+ */
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ for (i = 0; i < num_data; i++) {
+ krb5_crypto_iov *iov = &data[i];
+
+ switch (iov->flags) {
+ case KRB5_CRYPTO_TYPE_DATA:
+ data_length += iov->data.length;
+ break;
+ case KRB5_CRYPTO_TYPE_PADDING:
+ if (padding != NULL)
+ return EINVAL;
+
+ padding = iov;
+ break;
+ case KRB5_CRYPTO_TYPE_HEADER:
+ case KRB5_CRYPTO_TYPE_TRAILER:
+ case KRB5_CRYPTO_TYPE_CHECKSUM:
+ iov->data.length = ktp->crypto_length(ktp, iov->flags);
+ break;
+ case KRB5_CRYPTO_TYPE_EMPTY:
+ case KRB5_CRYPTO_TYPE_SIGN_ONLY:
+ default:
+ break;
+ }
+ }
+
+ pad_length = krb5int_c_padding_length(ktp, data_length);
+ if (pad_length != 0 && padding == NULL)
+ return EINVAL;
+
+ if (padding != NULL)
+ padding->data.length = pad_length;
+
+ return 0;
+}
diff --git a/src/lib/crypto/krb/crypto_libinit.c b/src/lib/crypto/krb/crypto_libinit.c
new file mode 100644
index 000000000000..3b62ff5de0eb
--- /dev/null
+++ b/src/lib/crypto/krb/crypto_libinit.c
@@ -0,0 +1,35 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#include "crypto_int.h"
+
+MAKE_INIT_FUNCTION(cryptoint_initialize_library);
+MAKE_FINI_FUNCTION(cryptoint_cleanup_library);
+
+/*
+ * Initialize the crypto library.
+ */
+
+int cryptoint_initialize_library (void)
+{
+ int err;
+ err = k5_prng_init();
+ if (err)
+ return err;
+ return krb5int_crypto_impl_init();
+}
+
+int krb5int_crypto_init(void)
+{
+ return CALL_INIT_FUNCTION(cryptoint_initialize_library);
+}
+
+/*
+ * Clean up the crypto library state
+ */
+
+void cryptoint_cleanup_library (void)
+{
+ if (!INITIALIZER_RAN(cryptoint_initialize_library))
+ return;
+ k5_prng_cleanup();
+ krb5int_crypto_impl_cleanup();
+}
diff --git a/src/lib/crypto/krb/decrypt.c b/src/lib/crypto/krb/decrypt.c
new file mode 100644
index 000000000000..496d262e9e66
--- /dev/null
+++ b/src/lib/crypto/krb/decrypt.c
@@ -0,0 +1,101 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_k_decrypt(krb5_context context, krb5_key key,
+ krb5_keyusage usage, const krb5_data *cipher_state,
+ const krb5_enc_data *input, krb5_data *output)
+{
+ const struct krb5_keytypes *ktp;
+ krb5_crypto_iov iov[4];
+ krb5_error_code ret;
+ unsigned int header_len, trailer_len, plain_len;
+ char *scratch = NULL;
+
+ ktp = find_enctype(key->keyblock.enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ if (input->enctype != ENCTYPE_UNKNOWN && ktp->etype != input->enctype)
+ return KRB5_BAD_ENCTYPE;
+
+ /* Verify the input and output lengths. */
+ header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER);
+ trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+ if (input->ciphertext.length < header_len + trailer_len)
+ return KRB5_BAD_MSIZE;
+ plain_len = input->ciphertext.length - header_len - trailer_len;
+ if (output->length < plain_len)
+ return KRB5_BAD_MSIZE;
+
+ scratch = k5alloc(header_len + trailer_len, &ret);
+ if (scratch == NULL)
+ return ret;
+
+ iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
+ iov[0].data = make_data(scratch, header_len);
+ memcpy(iov[0].data.data, input->ciphertext.data, header_len);
+
+ iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[1].data = make_data(output->data, plain_len);
+ memcpy(iov[1].data.data, input->ciphertext.data + header_len, plain_len);
+
+ /* Use empty padding since tokens don't indicate the padding length. */
+ iov[2].flags = KRB5_CRYPTO_TYPE_PADDING;
+ iov[2].data = empty_data();
+
+ iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER;
+ iov[3].data = make_data(scratch + header_len, trailer_len);
+ memcpy(iov[3].data.data, input->ciphertext.data + header_len + plain_len,
+ trailer_len);
+
+ ret = ktp->decrypt(ktp, key, usage, cipher_state, iov, 4);
+ if (ret != 0)
+ zap(output->data, plain_len);
+ else
+ output->length = plain_len;
+ zapfree(scratch, header_len + trailer_len);
+ return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_decrypt(krb5_context context, const krb5_keyblock *keyblock,
+ krb5_keyusage usage, const krb5_data *cipher_state,
+ const krb5_enc_data *input, krb5_data *output)
+{
+ krb5_key key;
+ krb5_error_code ret;
+
+ ret = krb5_k_create_key(context, keyblock, &key);
+ if (ret != 0)
+ return ret;
+ ret = krb5_k_decrypt(context, key, usage, cipher_state, input, output);
+ krb5_k_free_key(context, key);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/decrypt_iov.c b/src/lib/crypto/krb/decrypt_iov.c
new file mode 100644
index 000000000000..8d43e8ff6168
--- /dev/null
+++ b/src/lib/crypto/krb/decrypt_iov.c
@@ -0,0 +1,64 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/decrypt_iov.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 "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_k_decrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage,
+ const krb5_data *cipher_state, krb5_crypto_iov *data,
+ size_t num_data)
+{
+ const struct krb5_keytypes *ktp;
+
+ ktp = find_enctype(key->keyblock.enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ if (krb5int_c_locate_iov(data, num_data,
+ KRB5_CRYPTO_TYPE_STREAM) != NULL) {
+ return krb5int_c_iov_decrypt_stream(ktp, key, usage, cipher_state,
+ data, num_data);
+ }
+
+ return ktp->decrypt(ktp, key, usage, cipher_state, data, num_data);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_decrypt_iov(krb5_context context, const krb5_keyblock *keyblock,
+ krb5_keyusage usage, const krb5_data *cipher_state,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ krb5_key key;
+ krb5_error_code ret;
+
+ ret = krb5_k_create_key(context, keyblock, &key);
+ if (ret != 0)
+ return ret;
+ ret = krb5_k_decrypt_iov(context, key, usage, cipher_state, data,
+ num_data);
+ krb5_k_free_key(context, key);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/default_state.c b/src/lib/crypto/krb/default_state.c
new file mode 100644
index 000000000000..c7bfe323f799
--- /dev/null
+++ b/src/lib/crypto/krb/default_state.c
@@ -0,0 +1,54 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2001, 2014 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.
+ *
+ * Section 6 (Encryption) of the Kerberos revisions document defines
+ * cipher states to be used to chain encryptions and decryptions
+ * together. Examples of cipher states include initialization vectors
+ * for CBC encription. Most Kerberos encryption systems can share
+ * code for initializing and freeing cipher states. This file
+ * contains that default code.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_des_init_state(const krb5_keyblock *key, krb5_keyusage usage,
+ krb5_data *state_out)
+{
+ if (alloc_data(state_out, 8))
+ return ENOMEM;
+
+ /* des-cbc-crc uses the key as the initial ivec. */
+ if (key->enctype == ENCTYPE_DES_CBC_CRC)
+ memcpy(state_out->data, key->contents, state_out->length);
+
+ return 0;
+}
+
+void
+krb5int_default_free_state(krb5_data *state)
+{
+ free(state->data);
+ *state = empty_data();
+}
diff --git a/src/lib/crypto/krb/deps b/src/lib/crypto/krb/deps
new file mode 100644
index 000000000000..2a7f9b0effd3
--- /dev/null
+++ b/src/lib/crypto/krb/deps
@@ -0,0 +1,783 @@
+#
+# Generated makefile dependencies follow.
+#
+aead.so aead.po $(OUTPRE)aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ aead.c crypto_int.h
+block_size.so block_size.po $(OUTPRE)block_size.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h block_size.c crypto_int.h
+cf2.so cf2.po $(OUTPRE)cf2.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ cf2.c crypto_int.h
+checksum_cbc.so checksum_cbc.po $(OUTPRE)checksum_cbc.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h checksum_cbc.c \
+ crypto_int.h
+checksum_confounder.so checksum_confounder.po $(OUTPRE)checksum_confounder.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h checksum_confounder.c \
+ crypto_int.h
+checksum_dk_cmac.so checksum_dk_cmac.po $(OUTPRE)checksum_dk_cmac.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h checksum_dk_cmac.c \
+ crypto_int.h
+checksum_dk_hmac.so checksum_dk_hmac.po $(OUTPRE)checksum_dk_hmac.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h checksum_dk_hmac.c \
+ crypto_int.h
+checksum_etm.so checksum_etm.po $(OUTPRE)checksum_etm.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h checksum_etm.c \
+ crypto_int.h
+checksum_hmac_md5.so checksum_hmac_md5.po $(OUTPRE)checksum_hmac_md5.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h checksum_hmac_md5.c \
+ crypto_int.h
+checksum_unkeyed.so checksum_unkeyed.po $(OUTPRE)checksum_unkeyed.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h checksum_unkeyed.c \
+ crypto_int.h
+checksum_length.so checksum_length.po $(OUTPRE)checksum_length.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h checksum_length.c \
+ crypto_int.h
+cksumtype_to_string.so cksumtype_to_string.po $(OUTPRE)cksumtype_to_string.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h cksumtype_to_string.c \
+ crypto_int.h
+cksumtypes.so cksumtypes.po $(OUTPRE)cksumtypes.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h cksumtypes.c crypto_int.h
+cmac.so cmac.po $(OUTPRE)cmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ cmac.c crypto_int.h
+coll_proof_cksum.so coll_proof_cksum.po $(OUTPRE)coll_proof_cksum.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h coll_proof_cksum.c \
+ crypto_int.h
+combine_keys.so combine_keys.po $(OUTPRE)combine_keys.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h combine_keys.c \
+ crypto_int.h
+crc32.so crc32.po $(OUTPRE)crc32.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crc32.c crypto_int.h
+crypto_length.so crypto_length.po $(OUTPRE)crypto_length.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h crypto_length.c
+crypto_libinit.so crypto_libinit.po $(OUTPRE)crypto_libinit.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h crypto_libinit.c
+default_state.so default_state.po $(OUTPRE)default_state.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h default_state.c
+decrypt.so decrypt.po $(OUTPRE)decrypt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h decrypt.c
+decrypt_iov.so decrypt_iov.po $(OUTPRE)decrypt_iov.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h decrypt_iov.c
+derive.so derive.po $(OUTPRE)derive.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h derive.c
+encrypt.so encrypt.po $(OUTPRE)encrypt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h encrypt.c
+encrypt_iov.so encrypt_iov.po $(OUTPRE)encrypt_iov.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h encrypt_iov.c
+encrypt_length.so encrypt_length.po $(OUTPRE)encrypt_length.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h encrypt_length.c
+enctype_util.so enctype_util.po $(OUTPRE)enctype_util.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h enctype_util.c
+enc_dk_cmac.so enc_dk_cmac.po $(OUTPRE)enc_dk_cmac.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h enc_dk_cmac.c
+enc_dk_hmac.so enc_dk_hmac.po $(OUTPRE)enc_dk_hmac.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h enc_dk_hmac.c
+enc_etm.so enc_etm.po $(OUTPRE)enc_etm.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h enc_etm.c
+enc_old.so enc_old.po $(OUTPRE)enc_old.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h enc_old.c
+enc_raw.so enc_raw.po $(OUTPRE)enc_raw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h enc_raw.c
+enc_rc4.so enc_rc4.po $(OUTPRE)enc_rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h enc_rc4.c
+etypes.so etypes.po $(OUTPRE)etypes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h etypes.c
+key.so key.po $(OUTPRE)key.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h key.c
+keyblocks.so keyblocks.po $(OUTPRE)keyblocks.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h keyblocks.c
+keyed_cksum.so keyed_cksum.po $(OUTPRE)keyed_cksum.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h keyed_cksum.c
+keyed_checksum_types.so keyed_checksum_types.po $(OUTPRE)keyed_checksum_types.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h keyed_checksum_types.c
+keylengths.so keylengths.po $(OUTPRE)keylengths.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h keylengths.c
+make_checksum.so make_checksum.po $(OUTPRE)make_checksum.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h make_checksum.c
+make_checksum_iov.so make_checksum_iov.po $(OUTPRE)make_checksum_iov.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h make_checksum_iov.c
+make_random_key.so make_random_key.po $(OUTPRE)make_random_key.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h make_random_key.c
+mandatory_sumtype.so mandatory_sumtype.po $(OUTPRE)mandatory_sumtype.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h mandatory_sumtype.c
+nfold.so nfold.po $(OUTPRE)nfold.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h nfold.c
+old_api_glue.so old_api_glue.po $(OUTPRE)old_api_glue.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h old_api_glue.c
+prf.so prf.po $(OUTPRE)prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h prf.c
+prf_aes2.so prf_aes2.po $(OUTPRE)prf_aes2.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h prf_aes2.c
+prf_cmac.so prf_cmac.po $(OUTPRE)prf_cmac.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h prf_cmac.c
+prf_des.so prf_des.po $(OUTPRE)prf_des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h prf_des.c
+prf_dk.so prf_dk.po $(OUTPRE)prf_dk.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h prf_dk.c
+prf_rc4.so prf_rc4.po $(OUTPRE)prf_rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h prf_rc4.c
+prng.so prng.po $(OUTPRE)prng.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h prng.c
+prng_fortuna.so prng_fortuna.po $(OUTPRE)prng_fortuna.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h prng_fortuna.c
+random_to_key.so random_to_key.po $(OUTPRE)random_to_key.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h random_to_key.c
+s2k_des.so s2k_des.po $(OUTPRE)s2k_des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h s2k_des.c
+s2k_pbkdf2.so s2k_pbkdf2.po $(OUTPRE)s2k_pbkdf2.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h s2k_pbkdf2.c
+s2k_rc4.so s2k_rc4.po $(OUTPRE)s2k_rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h s2k_rc4.c
+state.so state.po $(OUTPRE)state.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \
+ $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ crypto_int.h state.c
+string_to_cksumtype.so string_to_cksumtype.po $(OUTPRE)string_to_cksumtype.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h string_to_cksumtype.c
+string_to_key.so string_to_key.po $(OUTPRE)string_to_key.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h string_to_key.c
+t_fortuna.so t_fortuna.po $(OUTPRE)t_fortuna.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h prng_fortuna.c \
+ t_fortuna.c
+valid_cksumtype.so valid_cksumtype.po $(OUTPRE)valid_cksumtype.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h valid_cksumtype.c
+verify_checksum.so verify_checksum.po $(OUTPRE)verify_checksum.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h verify_checksum.c
+verify_checksum_iov.so verify_checksum_iov.po $(OUTPRE)verify_checksum_iov.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \
+ $(srcdir)/../builtin/sha2/sha2.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h crypto_int.h verify_checksum_iov.c
diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c
new file mode 100644
index 000000000000..6707a7308259
--- /dev/null
+++ b/src/lib/crypto/krb/derive.c
@@ -0,0 +1,354 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+static krb5_key
+find_cached_dkey(struct derived_key *list, const krb5_data *constant)
+{
+ for (; list; list = list->next) {
+ if (data_eq(list->constant, *constant)) {
+ krb5_k_reference_key(NULL, list->dkey);
+ return list->dkey;
+ }
+ }
+ return NULL;
+}
+
+static krb5_error_code
+add_cached_dkey(krb5_key key, const krb5_data *constant,
+ const krb5_keyblock *dkeyblock, krb5_key *cached_dkey)
+{
+ krb5_key dkey;
+ krb5_error_code ret;
+ struct derived_key *dkent = NULL;
+ char *data = NULL;
+
+ /* Allocate fields for the new entry. */
+ dkent = malloc(sizeof(*dkent));
+ if (dkent == NULL)
+ goto cleanup;
+ data = k5memdup(constant->data, constant->length, &ret);
+ if (data == NULL)
+ goto cleanup;
+ ret = krb5_k_create_key(NULL, dkeyblock, &dkey);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Add the new entry to the list. */
+ dkent->dkey = dkey;
+ dkent->constant.data = data;
+ dkent->constant.length = constant->length;
+ dkent->next = key->derived;
+ key->derived = dkent;
+
+ /* Return a "copy" of the cached key. */
+ krb5_k_reference_key(NULL, dkey);
+ *cached_dkey = dkey;
+ return 0;
+
+cleanup:
+ free(dkent);
+ free(data);
+ return ENOMEM;
+}
+
+static krb5_error_code
+derive_random_rfc3961(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+ size_t blocksize, keybytes, n;
+ krb5_error_code ret;
+ krb5_data block = empty_data();
+
+ blocksize = enc->block_size;
+ keybytes = enc->keybytes;
+
+ if (blocksize == 1)
+ return KRB5_BAD_ENCTYPE;
+ if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
+ return KRB5_CRYPTO_INTERNAL;
+
+ /* Allocate encryption data buffer. */
+ ret = alloc_data(&block, blocksize);
+ if (ret)
+ return ret;
+
+ /* Initialize the input block. */
+ if (in_constant->length == blocksize) {
+ memcpy(block.data, in_constant->data, blocksize);
+ } else {
+ krb5int_nfold(in_constant->length * 8,
+ (unsigned char *) in_constant->data,
+ blocksize * 8, (unsigned char *) block.data);
+ }
+
+ /* Loop encrypting the blocks until enough key bytes are generated. */
+ n = 0;
+ while (n < keybytes) {
+ ret = encrypt_block(enc, inkey, &block);
+ if (ret)
+ goto cleanup;
+
+ if ((keybytes - n) <= blocksize) {
+ memcpy(outrnd->data + n, block.data, (keybytes - n));
+ break;
+ }
+
+ memcpy(outrnd->data + n, block.data, blocksize);
+ n += blocksize;
+ }
+
+cleanup:
+ zapfree(block.data, blocksize);
+ return ret;
+}
+
+/*
+ * NIST SP800-108 KDF in feedback mode (section 5.2).
+ * Parameters:
+ * - CMAC (with enc as the enc provider) is the PRF.
+ * - A block counter of four bytes is used.
+ * - Label is the key derivation constant.
+ * - Context is empty.
+ * - Four bytes are used to encode the output length in the PRF input.
+ */
+static krb5_error_code
+derive_random_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant)
+{
+ size_t blocksize, keybytes, n;
+ krb5_crypto_iov iov[6];
+ krb5_error_code ret;
+ krb5_data prf;
+ unsigned int i;
+ unsigned char ibuf[4], Lbuf[4];
+
+ blocksize = enc->block_size;
+ keybytes = enc->keybytes;
+
+ if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes)
+ return KRB5_CRYPTO_INTERNAL;
+
+ /* Allocate encryption data buffer. */
+ ret = alloc_data(&prf, blocksize);
+ if (ret)
+ return ret;
+
+ /* K(i-1): the previous block of PRF output, initially all-zeros. */
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[0].data = prf;
+ /* [i]2: four-byte big-endian binary string giving the block counter */
+ iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[1].data = make_data(ibuf, sizeof(ibuf));
+ /* Label: the fixed derived-key input */
+ iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[2].data = *in_constant;
+ /* 0x00: separator byte */
+ iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[3].data = make_data("", 1);
+ /* Context: (unused) */
+ iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[4].data = empty_data();
+ /* [L]2: four-byte big-endian binary string giving the output length */
+ iov[5].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[5].data = make_data(Lbuf, sizeof(Lbuf));
+ store_32_be(outrnd->length * 8, Lbuf);
+
+ for (i = 1, n = 0; n < keybytes; i++) {
+ /* Update the block counter. */
+ store_32_be(i, ibuf);
+
+ /* Compute a CMAC checksum, storing the result into K(i-1). */
+ ret = krb5int_cmac_checksum(enc, inkey, iov, 6, &prf);
+ if (ret)
+ goto cleanup;
+
+ /* Copy the result into the appropriate part of the output buffer. */
+ if (keybytes - n <= blocksize) {
+ memcpy(outrnd->data + n, prf.data, keybytes - n);
+ break;
+ }
+ memcpy(outrnd->data + n, prf.data, blocksize);
+ n += blocksize;
+ }
+
+cleanup:
+ zapfree(prf.data, blocksize);
+ return ret;
+}
+
+/*
+ * NIST SP800-108 KDF in counter mode (section 5.1).
+ * Parameters:
+ * - HMAC (with hash as the hash provider) is the PRF.
+ * - A block counter of four bytes is used.
+ * - Four bytes are used to encode the output length in the PRF input.
+ *
+ * There are no uses requiring more than a single PRF invocation.
+ */
+krb5_error_code
+k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *label, const krb5_data *context)
+{
+ krb5_crypto_iov iov[5];
+ krb5_error_code ret;
+ krb5_data prf;
+ unsigned char ibuf[4], lbuf[4];
+
+ if (hash == NULL || outrnd->length > hash->hashsize)
+ return KRB5_CRYPTO_INTERNAL;
+
+ /* Allocate encryption data buffer. */
+ ret = alloc_data(&prf, hash->hashsize);
+ if (ret)
+ return ret;
+
+ /* [i]2: four-byte big-endian binary string giving the block counter (1) */
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[0].data = make_data(ibuf, sizeof(ibuf));
+ store_32_be(1, ibuf);
+ /* Label */
+ iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[1].data = *label;
+ /* 0x00: separator byte */
+ iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[2].data = make_data("", 1);
+ /* Context */
+ iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[3].data = *context;
+ /* [L]2: four-byte big-endian binary string giving the output length */
+ iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[4].data = make_data(lbuf, sizeof(lbuf));
+ store_32_be(outrnd->length * 8, lbuf);
+
+ ret = krb5int_hmac(hash, inkey, iov, 5, &prf);
+ if (!ret)
+ memcpy(outrnd->data, prf.data, outrnd->length);
+ zapfree(prf.data, prf.length);
+ return ret;
+}
+
+krb5_error_code
+krb5int_derive_random(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_data *outrnd,
+ const krb5_data *in_constant, enum deriv_alg alg)
+{
+ krb5_data empty = empty_data();
+
+ switch (alg) {
+ case DERIVE_RFC3961:
+ return derive_random_rfc3961(enc, inkey, outrnd, in_constant);
+ case DERIVE_SP800_108_CMAC:
+ return derive_random_sp800_108_feedback_cmac(enc, inkey, outrnd,
+ in_constant);
+ case DERIVE_SP800_108_HMAC:
+ return k5_sp800_108_counter_hmac(hash, inkey, outrnd, in_constant,
+ &empty);
+ default:
+ return EINVAL;
+ }
+}
+
+/*
+ * Compute a derived key into the keyblock outkey. This variation on
+ * krb5int_derive_key does not cache the result, as it is only used
+ * directly in situations which are not expected to be repeated with
+ * the same inkey and constant.
+ */
+krb5_error_code
+krb5int_derive_keyblock(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_keyblock *outkey,
+ const krb5_data *in_constant, enum deriv_alg alg)
+{
+ krb5_error_code ret;
+ krb5_data rawkey = empty_data();
+
+ /* Allocate a buffer for the raw key bytes. */
+ ret = alloc_data(&rawkey, enc->keybytes);
+ if (ret)
+ goto cleanup;
+
+ /* Derive pseudo-random data for the key bytes. */
+ ret = krb5int_derive_random(enc, hash, inkey, &rawkey, in_constant, alg);
+ if (ret)
+ goto cleanup;
+
+ /* Postprocess the key. */
+ ret = krb5_c_random_to_key(NULL, inkey->keyblock.enctype, &rawkey, outkey);
+
+cleanup:
+ zapfree(rawkey.data, enc->keybytes);
+ return ret;
+}
+
+krb5_error_code
+krb5int_derive_key(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ krb5_key inkey, krb5_key *outkey,
+ const krb5_data *in_constant, enum deriv_alg alg)
+{
+ krb5_keyblock keyblock;
+ krb5_error_code ret;
+ krb5_key dkey;
+
+ *outkey = NULL;
+
+ /* Check for a cached result. */
+ dkey = find_cached_dkey(inkey->derived, in_constant);
+ if (dkey != NULL) {
+ *outkey = dkey;
+ return 0;
+ }
+
+ /* Derive into a temporary keyblock. */
+ keyblock.length = enc->keylength;
+ keyblock.contents = malloc(keyblock.length);
+ keyblock.enctype = inkey->keyblock.enctype;
+ if (keyblock.contents == NULL)
+ return ENOMEM;
+ ret = krb5int_derive_keyblock(enc, hash, inkey, &keyblock, in_constant,
+ alg);
+ if (ret)
+ goto cleanup;
+
+ /* Cache the derived key. */
+ ret = add_cached_dkey(inkey, in_constant, &keyblock, &dkey);
+ if (ret != 0)
+ goto cleanup;
+
+ *outkey = dkey;
+
+cleanup:
+ zapfree(keyblock.contents, keyblock.length);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/enc_dk_cmac.c b/src/lib/crypto/krb/enc_dk_cmac.c
new file mode 100644
index 000000000000..b65b9b70eb1c
--- /dev/null
+++ b/src/lib/crypto/krb/enc_dk_cmac.c
@@ -0,0 +1,182 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/enc_dk_cmac.c - Derived-key enctype functions using CMAC */
+/*
+ * Copyright 2008, 2009, 2010 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+
+#include "crypto_int.h"
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+/* AEAD */
+
+unsigned int
+krb5int_camellia_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type)
+{
+ switch (type) {
+ case KRB5_CRYPTO_TYPE_HEADER:
+ return ktp->enc->block_size;
+ case KRB5_CRYPTO_TYPE_PADDING:
+ return 0;
+ case KRB5_CRYPTO_TYPE_TRAILER:
+ case KRB5_CRYPTO_TYPE_CHECKSUM:
+ return ktp->enc->block_size;
+ default:
+ assert(0 && "bad type passed to krb5int_camellia_crypto_length");
+ return 0;
+ }
+}
+
+/* Derive encryption and integrity keys for CMAC-using enctypes. */
+static krb5_error_code
+derive_keys(const struct krb5_enc_provider *enc, krb5_key key,
+ krb5_keyusage usage, krb5_key *ke_out, krb5_key *ki_out)
+{
+ krb5_error_code ret;
+ unsigned char buf[K5CLENGTH];
+ krb5_data constant = make_data(buf, K5CLENGTH);
+ krb5_key ke, ki;
+
+ *ke_out = *ki_out = NULL;
+
+ /* Derive the encryption key. */
+ store_32_be(usage, buf);
+ buf[4] = 0xAA;
+ ret = krb5int_derive_key(enc, NULL, key, &ke, &constant,
+ DERIVE_SP800_108_CMAC);
+ if (ret != 0)
+ return ret;
+
+ /* Derive the integrity key. */
+ buf[4] = 0x55;
+ ret = krb5int_derive_key(enc, NULL, key, &ki, &constant,
+ DERIVE_SP800_108_CMAC);
+ if (ret != 0) {
+ krb5_k_free_key(NULL, ke);
+ return ret;
+ }
+
+ *ke_out = ke;
+ *ki_out = ki;
+ return 0;
+}
+
+krb5_error_code
+krb5int_dk_cmac_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ const struct krb5_enc_provider *enc = ktp->enc;
+ krb5_error_code ret;
+ krb5_crypto_iov *header, *trailer, *padding;
+ krb5_key ke = NULL, ki = NULL;
+
+ /* E(Confounder | Plaintext | Pad) | Checksum */
+
+ /* Validate header and trailer lengths, and zero out padding length. */
+ header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+ if (header == NULL || header->data.length < enc->block_size)
+ return KRB5_BAD_MSIZE;
+ trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+ if (trailer == NULL || trailer->data.length < enc->block_size)
+ return KRB5_BAD_MSIZE;
+ padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
+ if (padding != NULL)
+ padding->data.length = 0;
+
+ /* Derive the encryption and integrity keys. */
+ ret = derive_keys(enc, key, usage, &ke, &ki);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Generate confounder. */
+ header->data.length = enc->block_size;
+ ret = krb5_c_random_make_octets(NULL, &header->data);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Checksum the plaintext. */
+ ret = krb5int_cmac_checksum(enc, ki, data, num_data, &trailer->data);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Encrypt the plaintext (header | data | padding) */
+ ret = enc->encrypt(ke, ivec, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+
+cleanup:
+ krb5_k_free_key(NULL, ke);
+ krb5_k_free_key(NULL, ki);
+ return ret;
+}
+
+krb5_error_code
+krb5int_dk_cmac_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ const struct krb5_enc_provider *enc = ktp->enc;
+ krb5_error_code ret;
+ krb5_crypto_iov *header, *trailer;
+ krb5_data cksum = empty_data();
+ krb5_key ke = NULL, ki = NULL;
+
+ /* E(Confounder | Plaintext | Pad) | Checksum */
+
+ /* Validate header and trailer lengths. */
+ header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+ if (header == NULL || header->data.length != enc->block_size)
+ return KRB5_BAD_MSIZE;
+ trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+ if (trailer == NULL || trailer->data.length != enc->block_size)
+ return KRB5_BAD_MSIZE;
+
+ /* Derive the encryption and integrity keys. */
+ ret = derive_keys(enc, key, usage, &ke, &ki);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Decrypt the plaintext (header | data | padding). */
+ ret = enc->decrypt(ke, ivec, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Verify the hash. */
+ ret = alloc_data(&cksum, enc->block_size);
+ if (ret != 0)
+ goto cleanup;
+ ret = krb5int_cmac_checksum(enc, ki, data, num_data, &cksum);
+ if (ret != 0)
+ goto cleanup;
+ if (k5_bcmp(cksum.data, trailer->data.data, enc->block_size) != 0)
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+
+cleanup:
+ krb5_k_free_key(NULL, ke);
+ krb5_k_free_key(NULL, ki);
+ zapfree(cksum.data, cksum.length);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/enc_dk_hmac.c b/src/lib/crypto/krb/enc_dk_hmac.c
new file mode 100644
index 000000000000..713044c67d69
--- /dev/null
+++ b/src/lib/crypto/krb/enc_dk_hmac.c
@@ -0,0 +1,269 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/enc_dk_hmac.c */
+/*
+ * Copyright 2008, 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.
+ */
+
+
+#include "crypto_int.h"
+
+#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */
+
+/* AEAD */
+
+unsigned int
+krb5int_dk_crypto_length(const struct krb5_keytypes *ktp, krb5_cryptotype type)
+{
+ switch (type) {
+ case KRB5_CRYPTO_TYPE_HEADER:
+ case KRB5_CRYPTO_TYPE_PADDING:
+ return ktp->enc->block_size;
+ case KRB5_CRYPTO_TYPE_TRAILER:
+ case KRB5_CRYPTO_TYPE_CHECKSUM:
+ return ktp->hash->hashsize;
+ default:
+ assert(0 && "invalid cryptotype passed to krb5int_dk_crypto_length");
+ return 0;
+ }
+}
+
+unsigned int
+krb5int_aes_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type)
+{
+ switch (type) {
+ case KRB5_CRYPTO_TYPE_HEADER:
+ return ktp->enc->block_size;
+ case KRB5_CRYPTO_TYPE_PADDING:
+ return 0;
+ case KRB5_CRYPTO_TYPE_TRAILER:
+ case KRB5_CRYPTO_TYPE_CHECKSUM:
+ return 96 / 8;
+ default:
+ assert(0 && "invalid cryptotype passed to krb5int_aes_crypto_length");
+ return 0;
+ }
+}
+
+krb5_error_code
+krb5int_dk_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ const struct krb5_enc_provider *enc = ktp->enc;
+ const struct krb5_hash_provider *hash = ktp->hash;
+ krb5_error_code ret;
+ unsigned char constantdata[K5CLENGTH];
+ krb5_data d1, d2;
+ krb5_crypto_iov *header, *trailer, *padding;
+ krb5_key ke = NULL, ki = NULL;
+ size_t i;
+ unsigned int blocksize, hmacsize, plainlen = 0, padsize = 0;
+ unsigned char *cksum = NULL;
+
+ /* E(Confounder | Plaintext | Pad) | Checksum */
+
+ blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING);
+ hmacsize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+
+ for (i = 0; i < num_data; i++) {
+ krb5_crypto_iov *iov = &data[i];
+
+ if (iov->flags == KRB5_CRYPTO_TYPE_DATA)
+ plainlen += iov->data.length;
+ }
+
+ /* Validate header and trailer lengths. */
+
+ header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+ if (header == NULL || header->data.length < enc->block_size)
+ return KRB5_BAD_MSIZE;
+
+ trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+ if (trailer == NULL || trailer->data.length < hmacsize)
+ return KRB5_BAD_MSIZE;
+
+ if (blocksize != 0) {
+ /* Check that the input data is correctly padded. */
+ if (plainlen % blocksize)
+ padsize = blocksize - (plainlen % blocksize);
+ }
+
+ padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
+ if (padsize && (padding == NULL || padding->data.length < padsize))
+ return KRB5_BAD_MSIZE;
+
+ if (padding != NULL) {
+ memset(padding->data.data, 0, padsize);
+ padding->data.length = padsize;
+ }
+
+ cksum = k5alloc(hash->hashsize, &ret);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Derive the keys. */
+
+ d1.data = (char *)constantdata;
+ d1.length = K5CLENGTH;
+
+ store_32_be(usage, constantdata);
+
+ d1.data[4] = 0xAA;
+
+ ret = krb5int_derive_key(enc, NULL, key, &ke, &d1, DERIVE_RFC3961);
+ if (ret != 0)
+ goto cleanup;
+
+ d1.data[4] = 0x55;
+
+ ret = krb5int_derive_key(enc, NULL, key, &ki, &d1, DERIVE_RFC3961);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Generate confounder. */
+
+ header->data.length = enc->block_size;
+
+ ret = krb5_c_random_make_octets(/* XXX */ NULL, &header->data);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Hash the plaintext. */
+ d2.length = hash->hashsize;
+ d2.data = (char *)cksum;
+
+ ret = krb5int_hmac(hash, ki, data, num_data, &d2);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Encrypt the plaintext (header | data | padding) */
+ ret = enc->encrypt(ke, ivec, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Possibly truncate the hash */
+ assert(hmacsize <= d2.length);
+
+ memcpy(trailer->data.data, cksum, hmacsize);
+ trailer->data.length = hmacsize;
+
+cleanup:
+ krb5_k_free_key(NULL, ke);
+ krb5_k_free_key(NULL, ki);
+ free(cksum);
+ return ret;
+}
+
+krb5_error_code
+krb5int_dk_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ const struct krb5_enc_provider *enc = ktp->enc;
+ const struct krb5_hash_provider *hash = ktp->hash;
+ krb5_error_code ret;
+ unsigned char constantdata[K5CLENGTH];
+ krb5_data d1;
+ krb5_crypto_iov *header, *trailer;
+ krb5_key ke = NULL, ki = NULL;
+ size_t i;
+ unsigned int blocksize; /* enc block size, not confounder len */
+ unsigned int hmacsize, cipherlen = 0;
+ unsigned char *cksum = NULL;
+
+ /* E(Confounder | Plaintext | Pad) | Checksum */
+
+ blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING);
+ hmacsize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+
+ if (blocksize != 0) {
+ /* Check that the input data is correctly padded. */
+ for (i = 0; i < num_data; i++) {
+ const krb5_crypto_iov *iov = &data[i];
+
+ if (ENCRYPT_DATA_IOV(iov))
+ cipherlen += iov->data.length;
+ }
+ if (cipherlen % blocksize != 0)
+ return KRB5_BAD_MSIZE;
+ }
+
+ /* Validate header and trailer lengths */
+
+ header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+ if (header == NULL || header->data.length != enc->block_size)
+ return KRB5_BAD_MSIZE;
+
+ trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+ if (trailer == NULL || trailer->data.length != hmacsize)
+ return KRB5_BAD_MSIZE;
+
+ cksum = k5alloc(hash->hashsize, &ret);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Derive the keys. */
+
+ d1.data = (char *)constantdata;
+ d1.length = K5CLENGTH;
+
+ store_32_be(usage, constantdata);
+
+ d1.data[4] = 0xAA;
+
+ ret = krb5int_derive_key(enc, NULL, key, &ke, &d1, DERIVE_RFC3961);
+ if (ret != 0)
+ goto cleanup;
+
+ d1.data[4] = 0x55;
+
+ ret = krb5int_derive_key(enc, NULL, key, &ki, &d1, DERIVE_RFC3961);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Decrypt the plaintext (header | data | padding). */
+ ret = enc->decrypt(ke, ivec, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Verify the hash. */
+ d1.length = hash->hashsize; /* non-truncated length */
+ d1.data = (char *)cksum;
+
+ ret = krb5int_hmac(hash, ki, data, num_data, &d1);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Compare only the possibly truncated length. */
+ if (k5_bcmp(cksum, trailer->data.data, hmacsize) != 0) {
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto cleanup;
+ }
+
+cleanup:
+ krb5_k_free_key(NULL, ke);
+ krb5_k_free_key(NULL, ki);
+ free(cksum);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/enc_etm.c b/src/lib/crypto/krb/enc_etm.c
new file mode 100644
index 000000000000..3135dd5bb8d7
--- /dev/null
+++ b/src/lib/crypto/krb/enc_etm.c
@@ -0,0 +1,257 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/enc_etm.c - encrypt-then-mac construction for aes-sha2 */
+/*
+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "crypto_int.h"
+
+unsigned int
+krb5int_aes2_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type)
+{
+ switch (type) {
+ case KRB5_CRYPTO_TYPE_HEADER:
+ return ktp->enc->block_size;
+ case KRB5_CRYPTO_TYPE_PADDING:
+ return 0;
+ case KRB5_CRYPTO_TYPE_TRAILER:
+ case KRB5_CRYPTO_TYPE_CHECKSUM:
+ return ktp->hash->hashsize / 2;
+ default:
+ assert(0 && "invalid cryptotype passed to krb5int_aes2_crypto_length");
+ return 0;
+ }
+}
+
+/* Derive encryption and integrity keys for CMAC-using enctypes. */
+static krb5_error_code
+derive_keys(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, krb5_key *ke_out, krb5_data *ki_out)
+{
+ krb5_error_code ret;
+ uint8_t label[5];
+ krb5_data label_data = make_data(label, 5), ki = empty_data();
+ krb5_key ke = NULL;
+
+ *ke_out = NULL;
+ *ki_out = empty_data();
+
+ /* Derive the encryption key. */
+ store_32_be(usage, label);
+ label[4] = 0xAA;
+ ret = krb5int_derive_key(ktp->enc, ktp->hash, key, &ke, &label_data,
+ DERIVE_SP800_108_HMAC);
+ if (ret)
+ goto cleanup;
+
+ /* Derive the integrity key. */
+ label[4] = 0x55;
+ ret = alloc_data(&ki, ktp->hash->hashsize / 2);
+ if (ret)
+ goto cleanup;
+ ret = krb5int_derive_random(NULL, ktp->hash, key, &ki, &label_data,
+ DERIVE_SP800_108_HMAC);
+ if (ret)
+ goto cleanup;
+
+ *ke_out = ke;
+ ke = NULL;
+ *ki_out = ki;
+ ki = empty_data();
+
+cleanup:
+ krb5_k_free_key(NULL, ke);
+ zapfree(ki.data, ki.length);
+ return ret;
+}
+
+/* Compute an HMAC checksum over the cipher state and data. Allocate enough
+ * space in *out for the checksum. */
+static krb5_error_code
+hmac_ivec_data(const struct krb5_keytypes *ktp, const krb5_data *ki,
+ const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data,
+ krb5_data *out)
+{
+ krb5_error_code ret;
+ krb5_data zeroivec = empty_data();
+ krb5_crypto_iov *iovs = NULL;
+ krb5_keyblock kb = { 0 };
+
+ if (ivec == NULL) {
+ ret = ktp->enc->init_state(NULL, 0, &zeroivec);
+ if (ret)
+ goto cleanup;
+ ivec = &zeroivec;
+ }
+
+ /* Make a copy of data with an extra iov at the beginning for the ivec. */
+ iovs = k5calloc(num_data + 1, sizeof(*iovs), &ret);
+ if (iovs == NULL)
+ goto cleanup;
+ iovs[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ iovs[0].data = *ivec;
+ memcpy(iovs + 1, data, num_data * sizeof(*iovs));
+
+ ret = alloc_data(out, ktp->hash->hashsize);
+ if (ret)
+ goto cleanup;
+ kb.length = ki->length;
+ kb.contents = (uint8_t *)ki->data;
+ ret = krb5int_hmac_keyblock(ktp->hash, &kb, iovs, num_data + 1, out);
+
+cleanup:
+ if (zeroivec.data != NULL)
+ ktp->enc->free_state(&zeroivec);
+ free(iovs);
+ return ret;
+}
+
+krb5_error_code
+krb5int_etm_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ const struct krb5_enc_provider *enc = ktp->enc;
+ krb5_error_code ret;
+ krb5_data ivcopy = empty_data(), cksum = empty_data();
+ krb5_crypto_iov *header, *trailer, *padding;
+ krb5_key ke = NULL;
+ krb5_data ki = empty_data();
+ unsigned int trailer_len;
+
+ /* E(Confounder | Plaintext) | Checksum(IV | ciphertext) */
+
+ trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+
+ /* Validate header and trailer lengths, and zero out padding length. */
+ header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+ if (header == NULL || header->data.length < enc->block_size)
+ return KRB5_BAD_MSIZE;
+ trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+ if (trailer == NULL || trailer->data.length < trailer_len)
+ return KRB5_BAD_MSIZE;
+ padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
+ if (padding != NULL)
+ padding->data.length = 0;
+
+ if (ivec != NULL) {
+ ret = alloc_data(&ivcopy, ivec->length);
+ if (ret)
+ goto cleanup;
+ memcpy(ivcopy.data, ivec->data, ivec->length);
+ }
+
+ /* Derive the encryption and integrity keys. */
+ ret = derive_keys(ktp, key, usage, &ke, &ki);
+ if (ret)
+ goto cleanup;
+
+ /* Generate confounder. */
+ header->data.length = enc->block_size;
+ ret = krb5_c_random_make_octets(NULL, &header->data);
+ if (ret)
+ goto cleanup;
+
+ /* Encrypt the plaintext (header | data). */
+ ret = enc->encrypt(ke, (ivec == NULL) ? NULL : &ivcopy, data, num_data);
+ if (ret)
+ goto cleanup;
+
+ /* HMAC the IV, confounder, and ciphertext with sign-only data. */
+ ret = hmac_ivec_data(ktp, &ki, ivec, data, num_data, &cksum);
+ if (ret)
+ goto cleanup;
+
+ /* Truncate the HMAC checksum to the trailer length. */
+ assert(trailer_len <= cksum.length);
+ memcpy(trailer->data.data, cksum.data, trailer_len);
+ trailer->data.length = trailer_len;
+
+ /* Copy out the updated ivec if desired. */
+ if (ivec != NULL)
+ memcpy(ivec->data, ivcopy.data, ivcopy.length);
+
+cleanup:
+ krb5_k_free_key(NULL, ke);
+ zapfree(ki.data, ki.length);
+ free(cksum.data);
+ zapfree(ivcopy.data, ivcopy.length);
+ return ret;
+}
+
+krb5_error_code
+krb5int_etm_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ const struct krb5_enc_provider *enc = ktp->enc;
+ krb5_error_code ret;
+ krb5_data cksum = empty_data();
+ krb5_crypto_iov *header, *trailer;
+ krb5_key ke = NULL;
+ krb5_data ki = empty_data();
+ unsigned int trailer_len;
+
+ trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+
+ /* Validate header and trailer lengths. */
+ header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+ if (header == NULL || header->data.length != enc->block_size)
+ return KRB5_BAD_MSIZE;
+ trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+ if (trailer == NULL || trailer->data.length != trailer_len)
+ return KRB5_BAD_MSIZE;
+
+ /* Derive the encryption and integrity keys. */
+ ret = derive_keys(ktp, key, usage, &ke, &ki);
+ if (ret)
+ goto cleanup;
+
+ /* HMAC the IV, confounder, and ciphertext with sign-only data. */
+ ret = hmac_ivec_data(ktp, &ki, ivec, data, num_data, &cksum);
+ if (ret)
+ goto cleanup;
+
+ /* Compare only the possibly truncated length. */
+ assert(trailer_len <= cksum.length);
+ if (k5_bcmp(cksum.data, trailer->data.data, trailer_len) != 0) {
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto cleanup;
+ }
+
+ /* Decrypt the ciphertext (header | data | padding). */
+ ret = enc->decrypt(ke, ivec, data, num_data);
+
+cleanup:
+ krb5_k_free_key(NULL, ke);
+ zapfree(ki.data, ki.length);
+ zapfree(cksum.data, cksum.length);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/enc_old.c b/src/lib/crypto/krb/enc_old.c
new file mode 100644
index 000000000000..1b02a59157e4
--- /dev/null
+++ b/src/lib/crypto/krb/enc_old.c
@@ -0,0 +1,181 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/enc_old.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 "crypto_int.h"
+
+unsigned int
+krb5int_old_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type)
+{
+ switch (type) {
+ case KRB5_CRYPTO_TYPE_HEADER:
+ return ktp->enc->block_size + ktp->hash->hashsize;
+ case KRB5_CRYPTO_TYPE_PADDING:
+ return ktp->enc->block_size;
+ case KRB5_CRYPTO_TYPE_TRAILER:
+ return 0;
+ case KRB5_CRYPTO_TYPE_CHECKSUM:
+ return ktp->hash->hashsize;
+ default:
+ assert(0 && "invalid cryptotype passed to krb5int_old_crypto_length");
+ return 0;
+ }
+}
+
+krb5_error_code
+krb5int_old_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ const struct krb5_enc_provider *enc = ktp->enc;
+ const struct krb5_hash_provider *hash = ktp->hash;
+ krb5_error_code ret;
+ krb5_crypto_iov *header, *trailer, *padding;
+ krb5_data checksum, confounder, crcivec = empty_data();
+ unsigned int plainlen, padsize;
+ size_t i;
+
+ /* E(Confounder | Checksum | Plaintext | Pad) */
+
+ plainlen = enc->block_size + hash->hashsize;
+ for (i = 0; i < num_data; i++) {
+ krb5_crypto_iov *iov = &data[i];
+
+ if (iov->flags == KRB5_CRYPTO_TYPE_DATA)
+ plainlen += iov->data.length;
+ }
+
+ header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+ if (header == NULL ||
+ header->data.length < enc->block_size + hash->hashsize)
+ return KRB5_BAD_MSIZE;
+
+ /* Trailer may be absent. */
+ trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+ if (trailer != NULL)
+ trailer->data.length = 0;
+
+ /* Check that the input data is correctly padded. */
+ padsize = krb5_roundup(plainlen, enc->block_size) - plainlen;
+ padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
+ if (padsize > 0 && (padding == NULL || padding->data.length < padsize))
+ return KRB5_BAD_MSIZE;
+ if (padding) {
+ padding->data.length = padsize;
+ memset(padding->data.data, 0, padsize);
+ }
+
+ /* Generate a confounder in the header block. */
+ confounder = make_data(header->data.data, enc->block_size);
+ ret = krb5_c_random_make_octets(0, &confounder);
+ if (ret != 0)
+ goto cleanup;
+ checksum = make_data(header->data.data + enc->block_size, hash->hashsize);
+ memset(checksum.data, 0, hash->hashsize);
+
+ /* Checksum the plaintext with zeroed checksum and padding. */
+ ret = hash->hash(data, num_data, &checksum);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Use the key as the ivec for des-cbc-crc if none was provided. */
+ if (key->keyblock.enctype == ENCTYPE_DES_CBC_CRC && ivec == NULL) {
+ ret = alloc_data(&crcivec, key->keyblock.length);
+ if (ret != 0)
+ goto cleanup;
+ memcpy(crcivec.data, key->keyblock.contents, key->keyblock.length);
+ ivec = &crcivec;
+ }
+
+ ret = enc->encrypt(key, ivec, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+
+cleanup:
+ zapfree(crcivec.data, crcivec.length);
+ return ret;
+}
+
+krb5_error_code
+krb5int_old_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ const struct krb5_enc_provider *enc = ktp->enc;
+ const struct krb5_hash_provider *hash = ktp->hash;
+ krb5_error_code ret;
+ krb5_crypto_iov *header, *trailer;
+ krb5_data checksum, crcivec = empty_data();
+ char *saved_checksum = NULL;
+
+ /* Check that the input data is correctly padded. */
+ if (iov_total_length(data, num_data, FALSE) % enc->block_size != 0)
+ return KRB5_BAD_MSIZE;
+
+ header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
+ if (header == NULL ||
+ header->data.length != enc->block_size + hash->hashsize)
+ return KRB5_BAD_MSIZE;
+
+ trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
+ if (trailer != NULL && trailer->data.length != 0)
+ return KRB5_BAD_MSIZE;
+
+ /* Use the key as the ivec for des-cbc-crc if none was provided. */
+ if (key->keyblock.enctype == ENCTYPE_DES_CBC_CRC && ivec == NULL) {
+ ret = alloc_data(&crcivec, key->keyblock.length);
+ memcpy(crcivec.data, key->keyblock.contents, key->keyblock.length);
+ ivec = &crcivec;
+ }
+
+ /* Decrypt the ciphertext. */
+ ret = enc->decrypt(key, ivec, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Save the checksum, then zero it out in the plaintext. */
+ checksum = make_data(header->data.data + enc->block_size, hash->hashsize);
+ saved_checksum = k5memdup(checksum.data, checksum.length, &ret);
+ if (saved_checksum == NULL)
+ goto cleanup;
+ memset(checksum.data, 0, checksum.length);
+
+ /*
+ * Checksum the plaintext (with zeroed checksum field), storing the result
+ * back into the plaintext field we just zeroed out. Then compare it to
+ * the saved checksum.
+ */
+ ret = hash->hash(data, num_data, &checksum);
+ if (k5_bcmp(checksum.data, saved_checksum, checksum.length) != 0) {
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto cleanup;
+ }
+
+cleanup:
+ zapfree(crcivec.data, crcivec.length);
+ zapfree(saved_checksum, hash->hashsize);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/enc_raw.c b/src/lib/crypto/krb/enc_raw.c
new file mode 100644
index 000000000000..554d5c4d648d
--- /dev/null
+++ b/src/lib/crypto/krb/enc_raw.c
@@ -0,0 +1,109 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/enc_raw.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 "crypto_int.h"
+
+unsigned int
+krb5int_raw_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type)
+{
+ switch (type) {
+ case KRB5_CRYPTO_TYPE_PADDING:
+ return ktp->enc->block_size;
+ default:
+ return 0;
+ }
+}
+
+krb5_error_code
+krb5int_raw_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ krb5_crypto_iov *padding;
+ size_t i;
+ unsigned int blocksize, plainlen = 0, padsize = 0;
+
+ blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING);
+
+ for (i = 0; i < num_data; i++) {
+ krb5_crypto_iov *iov = &data[i];
+
+ if (iov->flags == KRB5_CRYPTO_TYPE_DATA)
+ plainlen += iov->data.length;
+ }
+
+ if (blocksize != 0) {
+ /* Check that the input data is correctly padded */
+ if (plainlen % blocksize)
+ padsize = blocksize - (plainlen % blocksize);
+ }
+
+ padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
+ if (padsize && (padding == NULL || padding->data.length < padsize))
+ return KRB5_BAD_MSIZE;
+
+ if (padding != NULL) {
+ memset(padding->data.data, 0, padsize);
+ padding->data.length = padsize;
+ }
+
+ return ktp->enc->encrypt(key, ivec, data, num_data);
+}
+
+krb5_error_code
+krb5int_raw_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ size_t i;
+ unsigned int blocksize = 0; /* enc block size, not confounder len */
+ unsigned int cipherlen = 0;
+
+ /* E(Confounder | Plaintext | Pad) | Checksum */
+
+ blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING);
+
+ for (i = 0; i < num_data; i++) {
+ const krb5_crypto_iov *iov = &data[i];
+
+ if (ENCRYPT_DATA_IOV(iov))
+ cipherlen += iov->data.length;
+ }
+
+ if (blocksize == 0) {
+ /* Check for correct input length in CTS mode */
+ if (ktp->enc->block_size != 0 && cipherlen < ktp->enc->block_size)
+ return KRB5_BAD_MSIZE;
+ } else {
+ /* Check that the input data is correctly padded */
+ if (cipherlen % blocksize != 0)
+ return KRB5_BAD_MSIZE;
+ }
+
+ return ktp->enc->decrypt(key, ivec, data, num_data);
+}
diff --git a/src/lib/crypto/krb/enc_rc4.c b/src/lib/crypto/krb/enc_rc4.c
new file mode 100644
index 000000000000..aac8508b137c
--- /dev/null
+++ b/src/lib/crypto/krb/enc_rc4.c
@@ -0,0 +1,347 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+
+ 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 "crypto_int.h"
+
+#define CONFOUNDERLENGTH 8
+
+const char l40[] = "fortybits";
+
+krb5_keyusage
+krb5int_arcfour_translate_usage(krb5_keyusage usage)
+{
+ switch (usage) {
+ case 1: return 1; /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, */
+ case 2: return 2; /* ticket from kdc */
+ case 3: return 8; /* as-rep encrypted part */
+ case 4: return 4; /* tgs-req authz data */
+ case 5: return 5; /* tgs-req authz data in subkey */
+ case 6: return 6; /* tgs-req authenticator cksum */
+ case 7: return 7; /* tgs-req authenticator */
+ case 8: return 8;
+ case 9: return 9; /* tgs-rep encrypted with subkey */
+ case 10: return 10; /* ap-rep authentication cksum (never used by MS) */
+ case 11: return 11; /* app-req authenticator */
+ case 12: return 12; /* app-rep encrypted part */
+ case 23: return 13; /* sign wrap token*/
+ default: return usage;
+ }
+}
+
+/* Derive a usage key from a session key and krb5 usage constant. */
+static krb5_error_code
+usage_key(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *session_keyblock, krb5_keyusage usage,
+ krb5_keyblock *out)
+{
+ char salt_buf[14];
+ unsigned int salt_len;
+ krb5_data out_data = make_data(out->contents, out->length);
+ krb5_crypto_iov iov;
+ krb5_keyusage ms_usage;
+
+ /* Generate the salt. */
+ ms_usage = krb5int_arcfour_translate_usage(usage);
+ if (session_keyblock->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
+ memcpy(salt_buf, l40, 10);
+ store_32_le(ms_usage, salt_buf + 10);
+ salt_len = 14;
+ } else {
+ store_32_le(ms_usage, salt_buf);
+ salt_len = 4;
+ }
+
+ /* Compute HMAC(key, salt) to produce the usage key. */
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = make_data(salt_buf, salt_len);
+ return krb5int_hmac_keyblock(hash, session_keyblock, &iov, 1, &out_data);
+}
+
+/* Derive an encryption key from a usage key and (typically) checksum. */
+static krb5_error_code
+enc_key(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *usage_keyblock, const krb5_data *checksum,
+ krb5_keyblock *out)
+{
+ krb5_keyblock *trunc_keyblock = NULL;
+ krb5_data out_data = make_data(out->contents, out->length);
+ krb5_crypto_iov iov;
+ krb5_error_code ret;
+
+ /* Copy usage_keyblock to trunc_keyblock and truncate if exportable. */
+ ret = krb5int_c_copy_keyblock(NULL, usage_keyblock, &trunc_keyblock);
+ if (ret != 0)
+ return ret;
+ if (trunc_keyblock->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
+ memset(trunc_keyblock->contents + 7, 0xab, 9);
+
+ /* Compute HMAC(trunc_key, checksum) to produce the encryption key. */
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = *checksum;
+ ret = krb5int_hmac_keyblock(hash, trunc_keyblock, &iov, 1, &out_data);
+ krb5int_c_free_keyblock(NULL, trunc_keyblock);
+ return ret;
+}
+
+unsigned int
+krb5int_arcfour_crypto_length(const struct krb5_keytypes *ktp,
+ krb5_cryptotype type)
+{
+ switch (type) {
+ case KRB5_CRYPTO_TYPE_HEADER:
+ return ktp->hash->hashsize + CONFOUNDERLENGTH;
+ case KRB5_CRYPTO_TYPE_PADDING:
+ case KRB5_CRYPTO_TYPE_TRAILER:
+ return 0;
+ case KRB5_CRYPTO_TYPE_CHECKSUM:
+ return ktp->hash->hashsize;
+ default:
+ assert(0 &&
+ "invalid cryptotype passed to krb5int_arcfour_crypto_length");
+ return 0;
+ }
+}
+
+/* Encrypt or decrypt using a keyblock. */
+static krb5_error_code
+keyblock_crypt(const struct krb5_enc_provider *enc, krb5_keyblock *keyblock,
+ const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data)
+{
+ krb5_error_code ret;
+ krb5_key key;
+
+ ret = krb5_k_create_key(NULL, keyblock, &key);
+ if (ret != 0)
+ return ret;
+ /* Works for encryption or decryption since arcfour is a stream cipher. */
+ ret = enc->encrypt(key, ivec, data, num_data);
+ krb5_k_free_key(NULL, key);
+ return ret;
+}
+
+krb5_error_code
+krb5int_arcfour_encrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ const struct krb5_enc_provider *enc = ktp->enc;
+ const struct krb5_hash_provider *hash = ktp->hash;
+ krb5_error_code ret;
+ krb5_crypto_iov *header, *trailer;
+ krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL;
+ krb5_data checksum, confounder, header_data;
+ size_t i;
+
+ /*
+ * 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 = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
+ &usage_keyblock);
+ if (ret != 0)
+ goto cleanup;
+ ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
+ &enc_keyblock);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Derive a usage key from the session key and usage. */
+ ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Generate a confounder in the header block, after the checksum. */
+ header->data.length = hash->hashsize + CONFOUNDERLENGTH;
+ confounder = make_data(header->data.data + hash->hashsize,
+ CONFOUNDERLENGTH);
+ ret = krb5_c_random_make_octets(0, &confounder);
+ if (ret != 0)
+ goto cleanup;
+ checksum = make_data(header->data.data, hash->hashsize);
+
+ /* Adjust pointers so confounder is at start of header. */
+ header->data.length -= hash->hashsize;
+ header->data.data += hash->hashsize;
+
+ /* Compute the checksum using the usage key. */
+ ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data,
+ &checksum);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Derive the encryption key from the usage key and checksum. */
+ ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock);
+ if (ret)
+ goto cleanup;
+
+ ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data);
+
+cleanup:
+ header->data = header_data; /* Restore header pointers. */
+ krb5int_c_free_keyblock(NULL, usage_keyblock);
+ krb5int_c_free_keyblock(NULL, enc_keyblock);
+ return ret;
+}
+
+krb5_error_code
+krb5int_arcfour_decrypt(const struct krb5_keytypes *ktp, krb5_key key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ const struct krb5_enc_provider *enc = ktp->enc;
+ const struct krb5_hash_provider *hash = ktp->hash;
+ krb5_error_code ret;
+ krb5_crypto_iov *header, *trailer;
+ krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL;
+ krb5_data checksum, header_data, comp_checksum = empty_data();
+
+ 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;
+
+ /* Allocate buffers. */
+ ret = alloc_data(&comp_checksum, hash->hashsize);
+ if (ret != 0)
+ goto cleanup;
+ ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
+ &usage_keyblock);
+ if (ret != 0)
+ goto cleanup;
+ ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes,
+ &enc_keyblock);
+ if (ret != 0)
+ goto cleanup;
+
+ checksum = make_data(header->data.data, hash->hashsize);
+
+ /* Adjust pointers so confounder is at start of header. */
+ header->data.length -= hash->hashsize;
+ header->data.data += hash->hashsize;
+
+ /* We may have to try two usage values; see below. */
+ do {
+ /* Derive a usage key from the session key and usage. */
+ ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Derive the encryption key from the usage key and checksum. */
+ ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock);
+ if (ret)
+ goto cleanup;
+
+ /* Decrypt the ciphertext. */
+ ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Compute HMAC(usage key, plaintext) to get the checksum. */
+ ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data,
+ &comp_checksum);
+ if (ret != 0)
+ goto cleanup;
+
+ if (k5_bcmp(checksum.data, comp_checksum.data, hash->hashsize) != 0) {
+ if (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. ivec is always NULL in this case.
+ * We need to re-encrypt the data in the wrong key first.
+ */
+ ret = keyblock_crypt(enc, enc_keyblock, NULL, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+ usage = 8;
+ continue;
+ }
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto cleanup;
+ }
+
+ break;
+ } while (1);
+
+cleanup:
+ header->data = header_data; /* Restore header pointers. */
+ krb5int_c_free_keyblock(NULL, usage_keyblock);
+ krb5int_c_free_keyblock(NULL, enc_keyblock);
+ zapfree(comp_checksum.data, comp_checksum.length);
+ return ret;
+}
+
+krb5_error_code
+krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage,
+ const krb5_data *kd_data, krb5_crypto_iov *data,
+ size_t num_data)
+{
+ const struct krb5_enc_provider *enc = &krb5int_enc_arcfour;
+ const struct krb5_hash_provider *hash = &krb5int_hash_md5;
+ krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL;
+ krb5_error_code ret;
+
+ ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes,
+ &usage_keyblock);
+ if (ret != 0)
+ goto cleanup;
+ ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes,
+ &enc_keyblock);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Derive a usage key from the session key and usage. */
+ ret = usage_key(enc, hash, keyblock, usage, usage_keyblock);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Derive the encryption key from the usage key and kd_data. */
+ ret = enc_key(enc, hash, usage_keyblock, kd_data, enc_keyblock);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Encrypt or decrypt (encrypt_iov works for both) the input. */
+ ret = keyblock_crypt(enc, enc_keyblock, 0, data, num_data);
+
+cleanup:
+ krb5int_c_free_keyblock(NULL, usage_keyblock);
+ krb5int_c_free_keyblock(NULL, enc_keyblock);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/encrypt.c b/src/lib/crypto/krb/encrypt.c
new file mode 100644
index 000000000000..d9d575a4dd46
--- /dev/null
+++ b/src/lib/crypto/krb/encrypt.c
@@ -0,0 +1,94 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_k_encrypt(krb5_context context, krb5_key key,
+ krb5_keyusage usage, const krb5_data *cipher_state,
+ const krb5_data *input, krb5_enc_data *output)
+{
+ const struct krb5_keytypes *ktp;
+ krb5_crypto_iov iov[4];
+ krb5_error_code ret;
+ unsigned int header_len, padding_len, trailer_len, total_len;
+
+ ktp = find_enctype(key->keyblock.enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ output->magic = KV5M_ENC_DATA;
+ output->kvno = 0;
+ output->enctype = key->keyblock.enctype;
+
+ /* Get the lengths of the token parts and compute the total. */
+ header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER);
+ padding_len = krb5int_c_padding_length(ktp, input->length);
+ trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+ total_len = header_len + input->length + padding_len + trailer_len;
+ if (output->ciphertext.length < total_len)
+ return KRB5_BAD_MSIZE;
+
+ /* Set up the iov structures for the token parts. */
+ iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
+ iov[0].data = make_data(output->ciphertext.data, header_len);
+
+ iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[1].data = make_data(output->ciphertext.data + header_len,
+ input->length);
+ if (input->length > 0)
+ memcpy(iov[1].data.data, input->data, input->length);
+
+ iov[2].flags = KRB5_CRYPTO_TYPE_PADDING;
+ iov[2].data = make_data(iov[1].data.data + input->length, padding_len);
+
+ iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER;
+ iov[3].data = make_data(iov[2].data.data + padding_len, trailer_len);
+
+ ret = ktp->encrypt(ktp, key, usage, cipher_state, iov, 4);
+ if (ret != 0)
+ zap(iov[1].data.data, iov[1].data.length);
+ else
+ output->ciphertext.length = total_len;
+ return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_encrypt(krb5_context context, const krb5_keyblock *keyblock,
+ krb5_keyusage usage, const krb5_data *cipher_state,
+ const krb5_data *input, krb5_enc_data *output)
+{
+ krb5_key key;
+ krb5_error_code ret;
+
+ ret = krb5_k_create_key(context, keyblock, &key);
+ if (ret != 0)
+ return ret;
+ ret = krb5_k_encrypt(context, key, usage, cipher_state, input, output);
+ krb5_k_free_key(context, key);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/encrypt_iov.c b/src/lib/crypto/krb/encrypt_iov.c
new file mode 100644
index 000000000000..d66fcfa527e2
--- /dev/null
+++ b/src/lib/crypto/krb/encrypt_iov.c
@@ -0,0 +1,58 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/encrypt_iov.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 "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_k_encrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage,
+ const krb5_data *cipher_state, krb5_crypto_iov *data,
+ size_t num_data)
+{
+ const struct krb5_keytypes *ktp;
+
+ ktp = find_enctype(key->keyblock.enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ return ktp->encrypt(ktp, key, usage, cipher_state, data, num_data);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_encrypt_iov(krb5_context context, const krb5_keyblock *keyblock,
+ krb5_keyusage usage, const krb5_data *cipher_state,
+ krb5_crypto_iov *data, size_t num_data)
+{
+ krb5_key key;
+ krb5_error_code ret;
+
+ ret = krb5_k_create_key(context, keyblock, &key);
+ if (ret != 0)
+ return ret;
+ ret = krb5_k_encrypt_iov(context, key, usage, cipher_state, data,
+ num_data);
+ krb5_k_free_key(context, key);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/encrypt_length.c b/src/lib/crypto/krb/encrypt_length.c
new file mode 100644
index 000000000000..5428e429c707
--- /dev/null
+++ b/src/lib/crypto/krb/encrypt_length.c
@@ -0,0 +1,47 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_encrypt_length(krb5_context context, krb5_enctype enctype,
+ size_t inputlen, size_t *length)
+{
+ const struct krb5_keytypes *ktp;
+ unsigned int header_len = 0, padding_len = 0, trailer_len = 0;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER);
+ padding_len = krb5int_c_padding_length(ktp, inputlen);
+ trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER);
+
+ *length = header_len + inputlen + padding_len + trailer_len;
+ return 0;
+}
diff --git a/src/lib/crypto/krb/enctype_util.c b/src/lib/crypto/krb/enctype_util.c
new file mode 100644
index 000000000000..0ed74bd6ebde
--- /dev/null
+++ b/src/lib/crypto/krb/enctype_util.c
@@ -0,0 +1,133 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/enctype_util.c */
+/*
+ * 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.
+ */
+
+/*
+ * krb5int_c_valid_enctype()
+ * krb5int_c_weak_enctype()
+ * krb5_c_enctype_compare()
+ * krb5_string_to_enctype()
+ * krb5_enctype_to_string()
+ */
+
+#include "crypto_int.h"
+
+krb5_boolean KRB5_CALLCONV
+krb5_c_valid_enctype(krb5_enctype etype)
+{
+ return (find_enctype(etype) != NULL);
+}
+
+krb5_boolean KRB5_CALLCONV
+krb5int_c_weak_enctype(krb5_enctype etype)
+{
+ const struct krb5_keytypes *ktp;
+
+ ktp = find_enctype(etype);
+ return (ktp != NULL && (ktp->flags & ETYPE_WEAK) != 0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_enctype_compare(krb5_context context, krb5_enctype e1, krb5_enctype e2,
+ krb5_boolean *similar)
+{
+ const struct krb5_keytypes *ktp1, *ktp2;
+
+ ktp1 = find_enctype(e1);
+ ktp2 = find_enctype(e2);
+ if (ktp1 == NULL || ktp2 == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ *similar = (ktp1->enc == ktp2->enc && ktp1->str2key == ktp2->str2key);
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_string_to_enctype(char *string, krb5_enctype *enctypep)
+{
+ int i;
+ unsigned int j;
+ const char *alias;
+ const struct krb5_keytypes *ktp;
+
+ for (i = 0; i < krb5int_enctypes_length; i++) {
+ ktp = &krb5int_enctypes_list[i];
+ if (strcasecmp(ktp->name, string) == 0) {
+ *enctypep = ktp->etype;
+ return 0;
+ }
+ for (j = 0; j < MAX_ETYPE_ALIASES; j++) {
+ alias = ktp->aliases[j];
+ if (alias == NULL)
+ break;
+ if (strcasecmp(alias, string) == 0) {
+ *enctypep = ktp->etype;
+ return 0;
+ }
+ }
+ }
+
+ return EINVAL;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_enctype_to_string(krb5_enctype enctype, char *buffer, size_t buflen)
+{
+ const struct krb5_keytypes *ktp;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return EINVAL;
+ if (strlcpy(buffer, ktp->out_string, buflen) >= buflen)
+ return ENOMEM;
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_enctype_to_name(krb5_enctype enctype, krb5_boolean shortest,
+ char *buffer, size_t buflen)
+{
+ const struct krb5_keytypes *ktp;
+ const char *name;
+ int i;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return EINVAL;
+ name = ktp->name;
+ if (shortest) {
+ for (i = 0; i < MAX_ETYPE_ALIASES; i++) {
+ if (ktp->aliases[i] == NULL)
+ break;
+ if (strlen(ktp->aliases[i]) < strlen(name))
+ name = ktp->aliases[i];
+ }
+ }
+ if (strlcpy(buffer, name, buflen) >= buflen)
+ return ENOMEM;
+ return 0;
+}
diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c
new file mode 100644
index 000000000000..0e5e977d418a
--- /dev/null
+++ b/src/lib/crypto/krb/etypes.c
@@ -0,0 +1,194 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+/* these will be linear searched. if they ever get big, a binary
+ search or hash table would be better, which means these would need
+ to be sorted. An array would be more efficient, but that assumes
+ that the keytypes are all near each other. I'd rather not make
+ that assumption. */
+
+const struct krb5_keytypes krb5int_enctypes_list[] = {
+ { ENCTYPE_DES_CBC_CRC,
+ "des-cbc-crc", { 0 }, "DES cbc mode with CRC-32",
+ &krb5int_enc_des, &krb5int_hash_crc32,
+ 16,
+ krb5int_old_crypto_length, krb5int_old_encrypt, krb5int_old_decrypt,
+ krb5int_des_string_to_key, k5_rand2key_des,
+ krb5int_des_prf,
+ CKSUMTYPE_RSA_MD5_DES,
+ ETYPE_WEAK },
+ { ENCTYPE_DES_CBC_MD4,
+ "des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4",
+ &krb5int_enc_des, &krb5int_hash_md4,
+ 16,
+ krb5int_old_crypto_length, krb5int_old_encrypt, krb5int_old_decrypt,
+ krb5int_des_string_to_key, k5_rand2key_des,
+ krb5int_des_prf,
+ CKSUMTYPE_RSA_MD4_DES,
+ ETYPE_WEAK },
+ { ENCTYPE_DES_CBC_MD5,
+ "des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5",
+ &krb5int_enc_des, &krb5int_hash_md5,
+ 16,
+ krb5int_old_crypto_length, krb5int_old_encrypt, krb5int_old_decrypt,
+ krb5int_des_string_to_key, k5_rand2key_des,
+ krb5int_des_prf,
+ CKSUMTYPE_RSA_MD5_DES,
+ ETYPE_WEAK },
+ { ENCTYPE_DES_CBC_RAW,
+ "des-cbc-raw", { 0 }, "DES cbc mode raw",
+ &krb5int_enc_des, NULL,
+ 16,
+ krb5int_raw_crypto_length, krb5int_raw_encrypt, krb5int_raw_decrypt,
+ krb5int_des_string_to_key, k5_rand2key_des,
+ krb5int_des_prf,
+ 0,
+ ETYPE_WEAK },
+ { ENCTYPE_DES3_CBC_RAW,
+ "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw",
+ &krb5int_enc_des3, NULL,
+ 16,
+ krb5int_raw_crypto_length, krb5int_raw_encrypt, krb5int_raw_decrypt,
+ krb5int_dk_string_to_key, k5_rand2key_des3,
+ NULL, /*PRF*/
+ 0,
+ ETYPE_WEAK },
+
+ { ENCTYPE_DES3_CBC_SHA1,
+ "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" },
+ "Triple DES cbc mode with HMAC/sha1",
+ &krb5int_enc_des3, &krb5int_hash_sha1,
+ 16,
+ krb5int_dk_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt,
+ krb5int_dk_string_to_key, k5_rand2key_des3,
+ krb5int_dk_prf,
+ CKSUMTYPE_HMAC_SHA1_DES3,
+ 0 /*flags*/ },
+
+ { ENCTYPE_DES_HMAC_SHA1,
+ "des-hmac-sha1", { 0 }, "DES with HMAC/sha1",
+ &krb5int_enc_des, &krb5int_hash_sha1,
+ 8,
+ krb5int_dk_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt,
+ krb5int_dk_string_to_key, k5_rand2key_des,
+ NULL, /*PRF*/
+ 0,
+ ETYPE_WEAK },
+ { ENCTYPE_ARCFOUR_HMAC,
+ "arcfour-hmac", { "rc4-hmac", "arcfour-hmac-md5" },
+ "ArcFour with HMAC/md5",
+ &krb5int_enc_arcfour,
+ &krb5int_hash_md5,
+ 20,
+ krb5int_arcfour_crypto_length, krb5int_arcfour_encrypt,
+ krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
+ k5_rand2key_direct, krb5int_arcfour_prf,
+ CKSUMTYPE_HMAC_MD5_ARCFOUR,
+ 0 /*flags*/ },
+ { ENCTYPE_ARCFOUR_HMAC_EXP,
+ "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" },
+ "Exportable ArcFour with HMAC/md5",
+ &krb5int_enc_arcfour,
+ &krb5int_hash_md5,
+ 20,
+ krb5int_arcfour_crypto_length, krb5int_arcfour_encrypt,
+ krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
+ k5_rand2key_direct, krb5int_arcfour_prf,
+ CKSUMTYPE_HMAC_MD5_ARCFOUR,
+ ETYPE_WEAK
+ },
+
+ { ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+ "aes128-cts-hmac-sha1-96", { "aes128-cts", "aes128-sha1" },
+ "AES-128 CTS mode with 96-bit SHA-1 HMAC",
+ &krb5int_enc_aes128, &krb5int_hash_sha1,
+ 16,
+ krb5int_aes_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt,
+ krb5int_aes_string_to_key, k5_rand2key_direct,
+ krb5int_dk_prf,
+ CKSUMTYPE_HMAC_SHA1_96_AES128,
+ 0 /*flags*/ },
+ { ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+ "aes256-cts-hmac-sha1-96", { "aes256-cts", "aes256-sha1" },
+ "AES-256 CTS mode with 96-bit SHA-1 HMAC",
+ &krb5int_enc_aes256, &krb5int_hash_sha1,
+ 16,
+ krb5int_aes_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt,
+ krb5int_aes_string_to_key, k5_rand2key_direct,
+ krb5int_dk_prf,
+ CKSUMTYPE_HMAC_SHA1_96_AES256,
+ 0 /*flags*/ },
+
+ { ENCTYPE_CAMELLIA128_CTS_CMAC,
+ "camellia128-cts-cmac", { "camellia128-cts" },
+ "Camellia-128 CTS mode with CMAC",
+ &krb5int_enc_camellia128, NULL,
+ 16,
+ krb5int_camellia_crypto_length,
+ krb5int_dk_cmac_encrypt, krb5int_dk_cmac_decrypt,
+ krb5int_camellia_string_to_key, k5_rand2key_direct,
+ krb5int_dk_cmac_prf,
+ CKSUMTYPE_CMAC_CAMELLIA128,
+ 0 /*flags*/ },
+ { ENCTYPE_CAMELLIA256_CTS_CMAC,
+ "camellia256-cts-cmac", { "camellia256-cts" },
+ "Camellia-256 CTS mode with CMAC",
+ &krb5int_enc_camellia256, NULL,
+ 16,
+ krb5int_camellia_crypto_length,
+ krb5int_dk_cmac_encrypt, krb5int_dk_cmac_decrypt,
+ krb5int_camellia_string_to_key, k5_rand2key_direct,
+ krb5int_dk_cmac_prf,
+ CKSUMTYPE_CMAC_CAMELLIA256,
+ 0 /*flags */ },
+
+ { ENCTYPE_AES128_CTS_HMAC_SHA256_128,
+ "aes128-cts-hmac-sha256-128", { "aes128-sha2" },
+ "AES-128 CTS mode with 128-bit SHA-256 HMAC",
+ &krb5int_enc_aes128, &krb5int_hash_sha256,
+ 32,
+ krb5int_aes2_crypto_length, krb5int_etm_encrypt, krb5int_etm_decrypt,
+ krb5int_aes2_string_to_key, k5_rand2key_direct,
+ krb5int_aes2_prf,
+ CKSUMTYPE_HMAC_SHA256_128_AES128,
+ 0 /*flags*/ },
+ { ENCTYPE_AES256_CTS_HMAC_SHA384_192,
+ "aes256-cts-hmac-sha384-192", { "aes256-sha2" },
+ "AES-256 CTS mode with 192-bit SHA-384 HMAC",
+ &krb5int_enc_aes256, &krb5int_hash_sha384,
+ 48,
+ krb5int_aes2_crypto_length, krb5int_etm_encrypt, krb5int_etm_decrypt,
+ krb5int_aes2_string_to_key, k5_rand2key_direct,
+ krb5int_aes2_prf,
+ CKSUMTYPE_HMAC_SHA384_192_AES256,
+ 0 /*flags*/ },
+};
+
+const int krb5int_enctypes_length =
+ sizeof(krb5int_enctypes_list) / sizeof(struct krb5_keytypes);
diff --git a/src/lib/crypto/krb/key.c b/src/lib/crypto/krb/key.c
new file mode 100644
index 000000000000..550ac20d376f
--- /dev/null
+++ b/src/lib/crypto/krb/key.c
@@ -0,0 +1,110 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 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.
+ *
+ * Functions for manipulating krb5_key structures
+ */
+
+#include "crypto_int.h"
+
+/*
+ * The krb5_key data type wraps an exposed keyblock in an opaque data
+ * structure, to allow for internal optimizations such as caching of
+ * derived keys.
+ */
+
+/* Create a krb5_key from the enctype and key data in a keyblock. */
+krb5_error_code KRB5_CALLCONV
+krb5_k_create_key(krb5_context context, const krb5_keyblock *key_data,
+ krb5_key *out)
+{
+ krb5_key key = NULL;
+ krb5_error_code code;
+
+ *out = NULL;
+
+ key = malloc(sizeof(*key));
+ if (key == NULL)
+ return ENOMEM;
+ code = krb5int_c_copy_keyblock_contents(context, key_data, &key->keyblock);
+ if (code)
+ goto cleanup;
+
+ key->refcount = 1;
+ key->derived = NULL;
+ key->cache = NULL;
+ *out = key;
+ return 0;
+
+cleanup:
+ free(key);
+ return code;
+}
+
+void KRB5_CALLCONV
+krb5_k_reference_key(krb5_context context, krb5_key key)
+{
+ if (key)
+ key->refcount++;
+}
+
+/* Free the memory used by a krb5_key. */
+void KRB5_CALLCONV
+krb5_k_free_key(krb5_context context, krb5_key key)
+{
+ struct derived_key *dk;
+ const struct krb5_keytypes *ktp;
+
+ if (key == NULL || --key->refcount > 0)
+ return;
+
+ /* Free the derived key cache. */
+ while ((dk = key->derived) != NULL) {
+ key->derived = dk->next;
+ free(dk->constant.data);
+ krb5_k_free_key(context, dk->dkey);
+ free(dk);
+ }
+ krb5int_c_free_keyblock_contents(context, &key->keyblock);
+ if (key->cache) {
+ ktp = find_enctype(key->keyblock.enctype);
+ if (ktp && ktp->enc->key_cleanup)
+ ktp->enc->key_cleanup(key);
+ }
+ free(key);
+}
+
+/* Retrieve a copy of the keyblock from a krb5_key. */
+krb5_error_code KRB5_CALLCONV
+krb5_k_key_keyblock(krb5_context context, krb5_key key,
+ krb5_keyblock **key_data)
+{
+ return krb5int_c_copy_keyblock(context, &key->keyblock, key_data);
+}
+
+/* Retrieve the enctype of a krb5_key. */
+krb5_enctype KRB5_CALLCONV
+krb5_k_key_enctype(krb5_context context, krb5_key key)
+{
+ return key->keyblock.enctype;
+}
diff --git a/src/lib/crypto/krb/keyblocks.c b/src/lib/crypto/krb/keyblocks.c
new file mode 100644
index 000000000000..98696f5086e1
--- /dev/null
+++ b/src/lib/crypto/krb/keyblocks.c
@@ -0,0 +1,108 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/keyblocks.c - Keyblock utility functions */
+/*
+ * Copyright (C) 2002, 2005 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_c_init_keyblock(krb5_context context, krb5_enctype enctype,
+ size_t length, krb5_keyblock **out)
+{
+ krb5_keyblock *kb;
+
+ assert(out);
+ *out = NULL;
+
+ kb = malloc(sizeof(krb5_keyblock));
+ if (kb == NULL)
+ return ENOMEM;
+ kb->magic = KV5M_KEYBLOCK;
+ kb->enctype = enctype;
+ kb->length = length;
+ if (length) {
+ kb->contents = malloc(length);
+ if (!kb->contents) {
+ free(kb);
+ return ENOMEM;
+ }
+ } else {
+ kb->contents = NULL;
+ }
+
+ *out = kb;
+ return 0;
+}
+
+void
+krb5int_c_free_keyblock(krb5_context context, register krb5_keyblock *val)
+{
+ krb5int_c_free_keyblock_contents(context, val);
+ free(val);
+}
+
+void
+krb5int_c_free_keyblock_contents(krb5_context context, krb5_keyblock *key)
+{
+ if (key && key->contents) {
+ zapfree(key->contents, key->length);
+ key->contents = NULL;
+ key->length = 0;
+ }
+}
+
+krb5_error_code
+krb5int_c_copy_keyblock(krb5_context context, const krb5_keyblock *from,
+ krb5_keyblock **to)
+{
+ krb5_keyblock *new_key;
+ krb5_error_code code;
+
+ *to = NULL;
+ new_key = malloc(sizeof(*new_key));
+ if (!new_key)
+ return ENOMEM;
+ code = krb5int_c_copy_keyblock_contents(context, from, new_key);
+ if (code) {
+ free(new_key);
+ return code;
+ }
+ *to = new_key;
+ return 0;
+}
+
+krb5_error_code
+krb5int_c_copy_keyblock_contents(krb5_context context,
+ const krb5_keyblock *from, krb5_keyblock *to)
+{
+ *to = *from;
+ if (to->length) {
+ to->contents = malloc(to->length);
+ if (!to->contents)
+ return ENOMEM;
+ memcpy(to->contents, from->contents, to->length);
+ } else
+ to->contents = 0;
+ return 0;
+}
diff --git a/src/lib/crypto/krb/keyed_checksum_types.c b/src/lib/crypto/krb/keyed_checksum_types.c
new file mode 100644
index 000000000000..4b211fb46b69
--- /dev/null
+++ b/src/lib/crypto/krb/keyed_checksum_types.c
@@ -0,0 +1,82 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+static krb5_boolean
+is_keyed_for(const struct krb5_cksumtypes *ctp,
+ const struct krb5_keytypes *ktp)
+{
+ if (ctp->flags & CKSUM_UNKEYED)
+ return FALSE;
+ return (!ctp->enc || ktp->enc == ctp->enc);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype,
+ unsigned int *count, krb5_cksumtype **cksumtypes)
+{
+ unsigned int i, c, nctypes;
+ krb5_cksumtype *ctypes;
+ const struct krb5_cksumtypes *ctp;
+ const struct krb5_keytypes *ktp;
+
+ *count = 0;
+ *cksumtypes = NULL;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ nctypes = 0;
+ for (i = 0; i < krb5int_cksumtypes_length; i++) {
+ ctp = &krb5int_cksumtypes_list[i];
+ if (is_keyed_for(ctp, ktp))
+ nctypes++;
+ }
+
+ ctypes = malloc(nctypes * sizeof(krb5_cksumtype));
+ if (ctypes == NULL)
+ return ENOMEM;
+
+ c = 0;
+ for (i = 0; i < krb5int_cksumtypes_length; i++) {
+ ctp = &krb5int_cksumtypes_list[i];
+ if (is_keyed_for(ctp, ktp))
+ ctypes[c++] = ctp->ctype;
+ }
+
+ *count = nctypes;
+ *cksumtypes = ctypes;
+ return 0;
+}
+
+void KRB5_CALLCONV
+krb5_free_cksumtypes(krb5_context context, krb5_cksumtype *val)
+{
+ free(val);
+}
diff --git a/src/lib/crypto/krb/keyed_cksum.c b/src/lib/crypto/krb/keyed_cksum.c
new file mode 100644
index 000000000000..d3db8f31b706
--- /dev/null
+++ b/src/lib/crypto/krb/keyed_cksum.c
@@ -0,0 +1,39 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_boolean KRB5_CALLCONV
+krb5_c_is_keyed_cksum(krb5_cksumtype ctype)
+{
+ const struct krb5_cksumtypes *ctp;
+
+ ctp = find_cksumtype(ctype);
+ if (ctp == NULL)
+ return FALSE;
+ return !(ctp->flags & CKSUM_UNKEYED);
+}
diff --git a/src/lib/crypto/krb/keylengths.c b/src/lib/crypto/krb/keylengths.c
new file mode 100644
index 000000000000..2bbd1cc6bdec
--- /dev/null
+++ b/src/lib/crypto/krb/keylengths.c
@@ -0,0 +1,57 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * COPYRIGHT (c) 2006
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include "crypto_int.h"
+
+/*
+ * keybytes is the number of bytes required as input to make a key,
+ * keylength is the length of the final key in bytes
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_c_keylengths(krb5_context context, krb5_enctype enctype,
+ size_t *keybytes, size_t *keylength)
+{
+ const struct krb5_keytypes *ktp;
+
+ if (keybytes == NULL && keylength == NULL)
+ return EINVAL;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ if (keybytes)
+ *keybytes = ktp->enc->keybytes;
+ if (keylength)
+ *keylength = ktp->enc->keylength;
+
+ return 0;
+}
diff --git a/src/lib/crypto/krb/make_checksum.c b/src/lib/crypto/krb/make_checksum.c
new file mode 100644
index 000000000000..398c84a8dbb1
--- /dev/null
+++ b/src/lib/crypto/krb/make_checksum.c
@@ -0,0 +1,99 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+/* A 0 checksum type means use the mandatory checksum. */
+
+krb5_error_code KRB5_CALLCONV
+krb5_k_make_checksum(krb5_context context, krb5_cksumtype cksumtype,
+ krb5_key key, krb5_keyusage usage,
+ const krb5_data *input, krb5_checksum *cksum)
+{
+ const struct krb5_cksumtypes *ctp;
+ krb5_crypto_iov iov;
+ krb5_data cksum_data;
+ krb5_octet *trunc;
+ krb5_error_code ret;
+
+ if (cksumtype == 0) {
+ ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype,
+ &cksumtype);
+ if (ret != 0)
+ return ret;
+ }
+ ctp = find_cksumtype(cksumtype);
+ if (ctp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ ret = verify_key(ctp, key);
+ if (ret != 0)
+ return ret;
+
+ ret = alloc_data(&cksum_data, ctp->compute_size);
+ if (ret != 0)
+ return ret;
+
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = *input;
+ ret = ctp->checksum(ctp, key, usage, &iov, 1, &cksum_data);
+ if (ret != 0)
+ goto cleanup;
+
+ cksum->magic = KV5M_CHECKSUM;
+ cksum->checksum_type = cksumtype;
+ cksum->length = ctp->output_size;
+ cksum->contents = (krb5_octet *) cksum_data.data;
+ cksum_data.data = NULL;
+ if (ctp->output_size < ctp->compute_size) {
+ trunc = realloc(cksum->contents, ctp->output_size);
+ if (trunc != NULL)
+ cksum->contents = trunc;
+ }
+
+cleanup:
+ zapfree(cksum_data.data, ctp->compute_size);
+ return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype,
+ const krb5_keyblock *keyblock, krb5_keyusage usage,
+ const krb5_data *input, krb5_checksum *cksum)
+{
+ krb5_key key = NULL;
+ krb5_error_code ret;
+
+ if (keyblock != NULL) {
+ ret = krb5_k_create_key(context, keyblock, &key);
+ if (ret != 0)
+ return ret;
+ }
+ ret = krb5_k_make_checksum(context, cksumtype, key, usage, input, cksum);
+ krb5_k_free_key(context, key);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/make_checksum_iov.c b/src/lib/crypto/krb/make_checksum_iov.c
new file mode 100644
index 000000000000..549180df515a
--- /dev/null
+++ b/src/lib/crypto/krb/make_checksum_iov.c
@@ -0,0 +1,94 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/make_checksum_iov.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 "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_k_make_checksum_iov(krb5_context context,
+ krb5_cksumtype cksumtype,
+ krb5_key key,
+ krb5_keyusage usage,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ krb5_error_code ret;
+ krb5_data cksum_data;
+ krb5_crypto_iov *checksum;
+ const struct krb5_cksumtypes *ctp;
+
+ if (cksumtype == 0) {
+ ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype,
+ &cksumtype);
+ if (ret != 0)
+ return ret;
+ }
+ ctp = find_cksumtype(cksumtype);
+ if (ctp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ ret = verify_key(ctp, key);
+ if (ret != 0)
+ return ret;
+
+ checksum = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
+ if (checksum == NULL || checksum->data.length < ctp->output_size)
+ return(KRB5_BAD_MSIZE);
+
+ ret = alloc_data(&cksum_data, ctp->compute_size);
+ if (ret != 0)
+ return ret;
+
+ ret = ctp->checksum(ctp, key, usage, data, num_data, &cksum_data);
+ if (ret != 0)
+ goto cleanup;
+
+ memcpy(checksum->data.data, cksum_data.data, ctp->output_size);
+ checksum->data.length = ctp->output_size;
+
+cleanup:
+ zapfree(cksum_data.data, ctp->compute_size);
+ return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_make_checksum_iov(krb5_context context,
+ krb5_cksumtype cksumtype,
+ const krb5_keyblock *keyblock,
+ krb5_keyusage usage,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ krb5_key key;
+ krb5_error_code ret;
+
+ ret = krb5_k_create_key(context, keyblock, &key);
+ if (ret != 0)
+ return ret;
+ ret = krb5_k_make_checksum_iov(context, cksumtype, key, usage,
+ data, num_data);
+ krb5_k_free_key(context, key);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/make_random_key.c b/src/lib/crypto/krb/make_random_key.c
new file mode 100644
index 000000000000..f5af18780eb7
--- /dev/null
+++ b/src/lib/crypto/krb/make_random_key.c
@@ -0,0 +1,76 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_make_random_key(krb5_context context, krb5_enctype enctype,
+ krb5_keyblock *random_key)
+{
+ krb5_error_code ret;
+ const struct krb5_keytypes *ktp;
+ const struct krb5_enc_provider *enc;
+ size_t keybytes, keylength;
+ krb5_data random_data;
+ unsigned char *bytes = NULL;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ enc = ktp->enc;
+
+ keybytes = enc->keybytes;
+ keylength = enc->keylength;
+
+ bytes = k5alloc(keybytes, &ret);
+ if (ret)
+ return ret;
+ random_key->contents = k5alloc(keylength, &ret);
+ if (ret)
+ goto cleanup;
+
+ random_data.data = (char *) bytes;
+ random_data.length = keybytes;
+
+ ret = krb5_c_random_make_octets(context, &random_data);
+ if (ret)
+ goto cleanup;
+
+ random_key->magic = KV5M_KEYBLOCK;
+ random_key->enctype = enctype;
+ random_key->length = keylength;
+
+ ret = (*ktp->rand2key)(&random_data, random_key);
+
+cleanup:
+ if (ret) {
+ zapfree(random_key->contents, keylength);
+ random_key->contents = NULL;
+ }
+ zapfree(bytes, keybytes);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/mandatory_sumtype.c b/src/lib/crypto/krb/mandatory_sumtype.c
new file mode 100644
index 000000000000..55ea81fa1803
--- /dev/null
+++ b/src/lib/crypto/krb/mandatory_sumtype.c
@@ -0,0 +1,39 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 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.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_c_mandatory_cksumtype(krb5_context ctx, krb5_enctype etype,
+ krb5_cksumtype *cksumtype)
+{
+ const struct krb5_keytypes *ktp;
+
+ ktp = find_enctype(etype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ *cksumtype = ktp->required_ctype;
+ return 0;
+}
diff --git a/src/lib/crypto/krb/nfold.c b/src/lib/crypto/krb/nfold.c
new file mode 100644
index 000000000000..ea02fddcf060
--- /dev/null
+++ b/src/lib/crypto/krb/nfold.c
@@ -0,0 +1,127 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+/*
+ * n-fold(k-bits):
+ * l = lcm(n,k)
+ * r = l/k
+ * s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1)
+ * compute the 1's complement sum:
+ * n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1]
+ */
+
+/* representation: msb first, assume n and k are multiples of 8, and
+ * that k>=16. this is the case of all the cryptosystems which are
+ * likely to be used. this function can be replaced if that
+ * assumption ever fails. */
+
+/* input length is in bits */
+
+void
+krb5int_nfold(unsigned int inbits, const unsigned char *in, unsigned int outbits,
+ unsigned char *out)
+{
+ int a,b,c,lcm;
+ int byte, i, msbit;
+
+ /* the code below is more readable if I make these bytes
+ instead of bits */
+
+ inbits >>= 3;
+ outbits >>= 3;
+
+ /* first compute lcm(n,k) */
+
+ a = outbits;
+ b = inbits;
+
+ while(b != 0) {
+ c = b;
+ b = a%b;
+ a = c;
+ }
+
+ lcm = outbits*inbits/a;
+
+ /* now do the real work */
+
+ memset(out, 0, outbits);
+ byte = 0;
+
+ /* this will end up cycling through k lcm(k,n)/k times, which
+ is correct */
+ for (i=lcm-1; i>=0; i--) {
+ /* compute the msbit in k which gets added into this byte */
+ msbit = (/* first, start with the msbit in the first, unrotated
+ byte */
+ ((inbits<<3)-1)
+ /* then, for each byte, shift to the right for each
+ repetition */
+ +(((inbits<<3)+13)*(i/inbits))
+ /* last, pick out the correct byte within that
+ shifted repetition */
+ +((inbits-(i%inbits))<<3)
+ )%(inbits<<3);
+
+ /* pull out the byte value itself */
+ byte += (((in[((inbits-1)-(msbit>>3))%inbits]<<8)|
+ (in[((inbits)-(msbit>>3))%inbits]))
+ >>((msbit&7)+1))&0xff;
+
+ /* do the addition */
+ byte += out[i%outbits];
+ out[i%outbits] = byte&0xff;
+
+#if 0
+ printf("msbit[%d] = %d\tbyte = %02x\tsum = %03x\n", i, msbit,
+ (((in[((inbits-1)-(msbit>>3))%inbits]<<8)|
+ (in[((inbits)-(msbit>>3))%inbits]))
+ >>((msbit&7)+1))&0xff, byte);
+#endif
+
+ /* keep around the carry bit, if any */
+ byte >>= 8;
+
+#if 0
+ printf("carry=%d\n", byte);
+#endif
+ }
+
+ /* if there's a carry bit left over, add it back in */
+ if (byte) {
+ for (i=outbits-1; i>=0; i--) {
+ /* do the addition */
+ byte += out[i];
+ out[i] = byte&0xff;
+
+ /* keep around the carry bit, if any */
+ byte >>= 8;
+ }
+ }
+}
diff --git a/src/lib/crypto/krb/old_api_glue.c b/src/lib/crypto/krb/old_api_glue.c
new file mode 100644
index 000000000000..b5bb280833fa
--- /dev/null
+++ b/src/lib/crypto/krb/old_api_glue.c
@@ -0,0 +1,390 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+/*
+ * The following functions were removed from the API in krb5 1.3 but
+ * still need to be exported for ABI compatibility. The other
+ * functions defined in this file are still in the API (and thus
+ * prototyped in krb5.hin) but are deprecated.
+ */
+krb5_boolean KRB5_CALLCONV valid_enctype(krb5_enctype ktype);
+krb5_boolean KRB5_CALLCONV valid_cksumtype(krb5_cksumtype ctype);
+krb5_boolean KRB5_CALLCONV is_coll_proof_cksum(krb5_cksumtype ctype);
+krb5_boolean KRB5_CALLCONV is_keyed_cksum(krb5_cksumtype ctype);
+krb5_error_code KRB5_CALLCONV krb5_random_confounder(size_t, krb5_pointer);
+krb5_error_code krb5_encrypt_data(krb5_context context, krb5_keyblock *key,
+ krb5_pointer ivec, krb5_data *data,
+ krb5_enc_data *enc_data);
+krb5_error_code krb5_decrypt_data(krb5_context context, krb5_keyblock *key,
+ krb5_pointer ivec, krb5_enc_data *data,
+ krb5_data *enc_data);
+
+krb5_error_code KRB5_CALLCONV
+krb5_encrypt(krb5_context context, krb5_const_pointer inptr,
+ krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock,
+ krb5_pointer ivec)
+{
+ krb5_data inputd, ivecd;
+ krb5_enc_data outputd;
+ size_t blocksize, outlen;
+ krb5_error_code ret;
+
+ if (ivec) {
+ ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize);
+ if (ret)
+ return ret;
+
+ ivecd = make_data(ivec, blocksize);
+ }
+
+ /* size is the length of the input cleartext data. */
+ inputd = make_data((void *) inptr, size);
+
+ /*
+ * The size of the output buffer isn't part of the old api. Not too
+ * safe. So, we assume here that it's big enough.
+ */
+ ret = krb5_c_encrypt_length(context, eblock->key->enctype, size, &outlen);
+ if (ret)
+ return ret;
+
+ outputd.ciphertext = make_data(outptr, outlen);
+
+ return krb5_c_encrypt(context, eblock->key, 0, ivec ? &ivecd : 0,
+ &inputd, &outputd);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_decrypt(krb5_context context, krb5_const_pointer inptr,
+ krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock,
+ krb5_pointer ivec)
+{
+ krb5_enc_data inputd;
+ krb5_data outputd, ivecd;
+ size_t blocksize;
+ krb5_error_code ret;
+
+ if (ivec) {
+ ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize);
+ if (ret)
+ return ret;
+
+ ivecd = make_data(ivec, blocksize);
+ }
+
+ /* size is the length of the input ciphertext data */
+ inputd.enctype = eblock->key->enctype;
+ inputd.ciphertext = make_data((void *) inptr, size);
+
+ /* we don't really know how big this is, but the code tends to assume
+ that the output buffer size should be the same as the input
+ buffer size */
+ outputd = make_data(outptr, size);
+
+ return krb5_c_decrypt(context, eblock->key, 0, ivec ? &ivecd : 0,
+ &inputd, &outputd);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_process_key(krb5_context context, krb5_encrypt_block *eblock,
+ const krb5_keyblock *key)
+{
+ eblock->key = (krb5_keyblock *) key;
+
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_finish_key(krb5_context context, krb5_encrypt_block *eblock)
+{
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_string_to_key(krb5_context context, const krb5_encrypt_block *eblock,
+ krb5_keyblock *keyblock, const krb5_data *data,
+ const krb5_data *salt)
+{
+ return krb5_c_string_to_key(context, eblock->crypto_entry, data, salt,
+ keyblock);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_init_random_key(krb5_context context, const krb5_encrypt_block *eblock,
+ const krb5_keyblock *keyblock, krb5_pointer *ptr)
+{
+ krb5_data data = make_data(keyblock->contents, keyblock->length);
+
+ return krb5_c_random_seed(context, &data);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_finish_random_key(krb5_context context, const krb5_encrypt_block *eblock,
+ krb5_pointer *ptr)
+{
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_random_key(krb5_context context, const krb5_encrypt_block *eblock,
+ krb5_pointer ptr, krb5_keyblock **keyblock)
+{
+ krb5_keyblock *key;
+ krb5_error_code ret;
+
+ *keyblock = NULL;
+
+ key = malloc(sizeof(krb5_keyblock));
+ if (key == NULL)
+ return ENOMEM;
+
+ ret = krb5_c_make_random_key(context, eblock->crypto_entry, key);
+ if (ret) {
+ free(key);
+ return ret;
+ }
+
+ *keyblock = key;
+ return(ret);
+}
+
+krb5_enctype KRB5_CALLCONV
+krb5_eblock_enctype(krb5_context context, const krb5_encrypt_block *eblock)
+{
+ return eblock->crypto_entry;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_use_enctype(krb5_context context, krb5_encrypt_block *eblock,
+ krb5_enctype enctype)
+{
+ eblock->crypto_entry = enctype;
+
+ return 0;
+}
+
+size_t KRB5_CALLCONV
+krb5_encrypt_size(size_t length, krb5_enctype crypto)
+{
+ size_t ret;
+
+ if (krb5_c_encrypt_length(NULL, crypto, length, &ret))
+ return (size_t) -1; /* XXX */
+
+ return ret;
+}
+
+size_t KRB5_CALLCONV
+krb5_checksum_size(krb5_context context, krb5_cksumtype ctype)
+{
+ size_t ret;
+
+ if (krb5_c_checksum_length(context, ctype, &ret))
+ return (size_t) -1; /* XXX */
+
+ return ret;
+}
+
+/* Guess the enctype for an untyped key used with checksum type ctype. */
+static krb5_enctype
+guess_enctype(krb5_cksumtype ctype)
+{
+ const struct krb5_cksumtypes *ctp;
+ int i;
+
+ if (ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR)
+ return ENCTYPE_ARCFOUR_HMAC;
+ ctp = find_cksumtype(ctype);
+ if (ctp == NULL || ctp->enc == NULL)
+ return 0;
+ for (i = 0; i < krb5int_enctypes_length; i++) {
+ if (krb5int_enctypes_list[i].enc == ctp->enc)
+ return i;
+ }
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_calculate_checksum(krb5_context context, krb5_cksumtype ctype,
+ krb5_const_pointer in, size_t in_length,
+ krb5_const_pointer seed, size_t seed_length,
+ krb5_checksum *outcksum)
+{
+ krb5_data input = make_data((void *) in, in_length);
+ krb5_keyblock keyblock, *kptr = NULL;
+ krb5_error_code ret;
+ krb5_checksum cksum;
+
+ if (seed != NULL) {
+ keyblock.enctype = guess_enctype(ctype);
+ keyblock.length = seed_length;
+ keyblock.contents = (unsigned char *) seed;
+ kptr = &keyblock;
+ }
+
+ ret = krb5_c_make_checksum(context, ctype, kptr, 0, &input, &cksum);
+ if (ret)
+ return ret;
+
+ if (outcksum->length < cksum.length) {
+ memset(cksum.contents, 0, cksum.length);
+ free(cksum.contents);
+ return KRB5_BAD_MSIZE;
+ }
+
+ outcksum->magic = cksum.magic;
+ outcksum->checksum_type = cksum.checksum_type;
+ memcpy(outcksum->contents, cksum.contents, cksum.length);
+ outcksum->length = cksum.length;
+
+ free(cksum.contents);
+
+ return(0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype,
+ const krb5_checksum *cksum, krb5_const_pointer in,
+ size_t in_length, krb5_const_pointer seed,
+ size_t seed_length)
+{
+ krb5_data input = make_data((void *) in, in_length);
+ krb5_keyblock keyblock, *kptr = NULL;
+ krb5_error_code ret;
+ krb5_boolean valid;
+
+ if (seed != NULL) {
+ keyblock.enctype = guess_enctype(ctype);
+ keyblock.length = seed_length;
+ keyblock.contents = (unsigned char *) seed;
+ kptr = &keyblock;
+ }
+
+ ret = krb5_c_verify_checksum(context, kptr, 0, &input, cksum, &valid);
+ if (ret)
+ return ret;
+
+ if (!valid)
+ return KRB5KRB_AP_ERR_BAD_INTEGRITY;
+
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_random_confounder(size_t size, krb5_pointer ptr)
+{
+ krb5_data random_data = make_data(ptr, size);
+
+ return krb5_c_random_make_octets(NULL, &random_data);
+}
+
+krb5_error_code krb5_encrypt_data(krb5_context context, krb5_keyblock *key,
+ krb5_pointer ivec, krb5_data *data,
+ krb5_enc_data *enc_data)
+{
+ krb5_error_code ret;
+ size_t enclen, blocksize;
+ krb5_data ivecd;
+
+ ret = krb5_c_encrypt_length(context, key->enctype, data->length, &enclen);
+ if (ret)
+ return ret;
+
+ if (ivec) {
+ ret = krb5_c_block_size(context, key->enctype, &blocksize);
+ if (ret)
+ return ret;
+
+ ivecd = make_data(ivec, blocksize);
+ }
+
+ enc_data->magic = KV5M_ENC_DATA;
+ enc_data->kvno = 0;
+ enc_data->enctype = key->enctype;
+ ret = alloc_data(&enc_data->ciphertext, enclen);
+ if (ret)
+ return ret;
+
+ ret = krb5_c_encrypt(context, key, 0, ivec ? &ivecd : 0, data, enc_data);
+ if (ret)
+ free(enc_data->ciphertext.data);
+
+ return ret;
+}
+
+krb5_error_code krb5_decrypt_data(krb5_context context, krb5_keyblock *key,
+ krb5_pointer ivec, krb5_enc_data *enc_data,
+ krb5_data *data)
+{
+ krb5_error_code ret;
+ krb5_data ivecd;
+ size_t blocksize;
+
+ if (ivec) {
+ ret = krb5_c_block_size(context, key->enctype, &blocksize);
+ if (ret)
+ return ret;
+
+ ivecd = make_data(ivec, blocksize);
+ }
+
+ ret = alloc_data(data, enc_data->ciphertext.length);
+ if (ret)
+ return ret;
+
+ ret = krb5_c_decrypt(context, key, 0, ivec ? &ivecd : 0, enc_data, data);
+ if (ret)
+ free(data->data);
+
+ return 0;
+}
+
+krb5_boolean KRB5_CALLCONV
+valid_cksumtype(krb5_cksumtype ctype)
+{
+ return krb5_c_valid_cksumtype(ctype);
+}
+
+krb5_boolean KRB5_CALLCONV
+is_keyed_cksum(krb5_cksumtype ctype)
+{
+ return krb5_c_is_keyed_cksum(ctype);
+}
+
+krb5_boolean KRB5_CALLCONV
+is_coll_proof_cksum(krb5_cksumtype ctype)
+{
+ return krb5_c_is_coll_proof_cksum(ctype);
+}
+
+krb5_boolean KRB5_CALLCONV
+valid_enctype(krb5_enctype etype)
+{
+ return krb5_c_valid_enctype(etype);
+}
diff --git a/src/lib/crypto/krb/prf.c b/src/lib/crypto/krb/prf.c
new file mode 100644
index 000000000000..67b856a9b6c0
--- /dev/null
+++ b/src/lib/crypto/krb/prf.c
@@ -0,0 +1,84 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/prf.c */
+/*
+ * Copyright (C) 2004 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 contains the implementation of krb5_c_prf, which will find the
+ * enctype-specific PRF and then generate pseudo-random data. This function
+ * yields krb5_c_prf_length bytes of output.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_prf_length(krb5_context context, krb5_enctype enctype, size_t *len)
+{
+ const struct krb5_keytypes *ktp;
+
+ assert(len);
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ *len = ktp->prf_length;
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_k_prf(krb5_context context, krb5_key key,
+ krb5_data *input, krb5_data *output)
+{
+ const struct krb5_keytypes *ktp;
+ krb5_error_code ret;
+
+ assert(input && output);
+ assert(output->data);
+
+ ktp = find_enctype(key->keyblock.enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ if (ktp->prf == NULL)
+ return KRB5_CRYPTO_INTERNAL;
+
+ output->magic = KV5M_DATA;
+ if (ktp->prf_length != output->length)
+ return KRB5_CRYPTO_INTERNAL;
+ ret = ktp->prf(ktp, key, input, output);
+ return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_prf(krb5_context context, const krb5_keyblock *keyblock,
+ krb5_data *input, krb5_data *output)
+{
+ krb5_key key;
+ krb5_error_code ret;
+
+ ret = krb5_k_create_key(context, keyblock, &key);
+ if (ret != 0)
+ return ret;
+ ret = krb5_k_prf(context, key, input, output);
+ krb5_k_free_key(context, key);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/prf_aes2.c b/src/lib/crypto/krb/prf_aes2.c
new file mode 100644
index 000000000000..9a5cffc56cb2
--- /dev/null
+++ b/src/lib/crypto/krb/prf_aes2.c
@@ -0,0 +1,42 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/prf_aes2.c - PRF for aes-sha2 enctypes */
+/*
+ * Copyright (C) 2015 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_aes2_prf(const struct krb5_keytypes *ktp, krb5_key key,
+ const krb5_data *in, krb5_data *out)
+{
+ krb5_data label = string2data("prf");
+
+ return k5_sp800_108_counter_hmac(ktp->hash, key, out, &label, in);
+}
diff --git a/src/lib/crypto/krb/prf_cmac.c b/src/lib/crypto/krb/prf_cmac.c
new file mode 100644
index 000000000000..1d4cc4c39501
--- /dev/null
+++ b/src/lib/crypto/krb/prf_cmac.c
@@ -0,0 +1,58 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/prf_cmac.c - CMAC-based PRF */
+/*
+ * Copyright (C) 2010 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_dk_cmac_prf(const struct krb5_keytypes *ktp, krb5_key key,
+ const krb5_data *in, krb5_data *out)
+{
+ krb5_crypto_iov iov;
+ krb5_data prfconst = make_data("prf", 3);
+ krb5_key kp = NULL;
+ krb5_error_code ret;
+
+ if (ktp->prf_length != ktp->enc->block_size)
+ return KRB5_BAD_MSIZE;
+
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = *in;
+
+ /* Derive a key using the PRF constant. */
+ ret = krb5int_derive_key(ktp->enc, NULL, key, &kp, &prfconst,
+ DERIVE_SP800_108_CMAC);
+ if (ret != 0)
+ goto cleanup;
+
+ /* PRF is CMAC of input */
+ ret = krb5int_cmac_checksum(ktp->enc, kp, &iov, 1, out);
+ if (ret != 0)
+ goto cleanup;
+
+cleanup:
+ krb5_k_free_key(NULL, kp);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/prf_des.c b/src/lib/crypto/krb/prf_des.c
new file mode 100644
index 000000000000..7a2d719c5f9f
--- /dev/null
+++ b/src/lib/crypto/krb/prf_des.c
@@ -0,0 +1,47 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/prf_des.c - RFC 3961 DES-based PRF */
+/*
+ * 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.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_des_prf(const struct krb5_keytypes *ktp, krb5_key key,
+ const krb5_data *in, krb5_data *out)
+{
+ const struct krb5_hash_provider *hash = &krb5int_hash_md5;
+ krb5_crypto_iov iov;
+ krb5_error_code ret;
+
+ /* Compute a hash of the input, storing into the output buffer. */
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = *in;
+ ret = hash->hash(&iov, 1, out);
+ if (ret != 0)
+ return ret;
+
+ /* Encrypt the hash in place. */
+ iov.data = *out;
+ return ktp->enc->encrypt(key, NULL, &iov, 1);
+}
diff --git a/src/lib/crypto/krb/prf_dk.c b/src/lib/crypto/krb/prf_dk.c
new file mode 100644
index 000000000000..544418bab74e
--- /dev/null
+++ b/src/lib/crypto/krb/prf_dk.c
@@ -0,0 +1,70 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/prf_dk.c - RFC 3961 simplified profile PRF */
+/*
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_dk_prf(const struct krb5_keytypes *ktp, krb5_key key,
+ const krb5_data *in, krb5_data *out)
+{
+ const struct krb5_enc_provider *enc = ktp->enc;
+ const struct krb5_hash_provider *hash = ktp->hash;
+ krb5_crypto_iov iov;
+ krb5_data cksum = empty_data(), prfconst = make_data("prf", 3);
+ krb5_key kp = NULL;
+ krb5_error_code ret;
+
+ /* Hash the input data into an allocated buffer. */
+ ret = alloc_data(&cksum, hash->hashsize);
+ if (ret != 0)
+ goto cleanup;
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = *in;
+ ret = hash->hash(&iov, 1, &cksum);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Derive a key using the PRF constant. */
+ ret = krb5int_derive_key(ktp->enc, NULL, key, &kp, &prfconst,
+ DERIVE_RFC3961);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Truncate the hash to the closest multiple of the block size. */
+ iov.data.data = cksum.data;
+ iov.data.length = (hash->hashsize / enc->block_size) * enc->block_size;
+
+ /* Encrypt the truncated hash in the derived key to get the output. */
+ ret = ktp->enc->encrypt(kp, NULL, &iov, 1);
+ if (ret != 0)
+ goto cleanup;
+ memcpy(out->data, iov.data.data, out->length);
+
+cleanup:
+ zapfree(cksum.data, hash->hashsize);
+ krb5_k_free_key(NULL, kp);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/prf_rc4.c b/src/lib/crypto/krb/prf_rc4.c
new file mode 100644
index 000000000000..092795321e51
--- /dev/null
+++ b/src/lib/crypto/krb/prf_rc4.c
@@ -0,0 +1,39 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/prf_rc4.c */
+/*
+ * Copyright (C) 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.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code
+krb5int_arcfour_prf(const struct krb5_keytypes *ktp, krb5_key key,
+ const krb5_data *in, krb5_data *out)
+{
+ krb5_crypto_iov iov;
+
+ assert(out->length == 20);
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = *in;
+ return krb5int_hmac(&krb5int_hash_sha1, key, &iov, 1, out);
+}
diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c
new file mode 100644
index 000000000000..cb9ca9b983d1
--- /dev/null
+++ b/src/lib/crypto/krb/prng.c
@@ -0,0 +1,134 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2001, 2002, 2004, 2007, 2008, 2010 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_seed(krb5_context context, krb5_data *data)
+{
+ return krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_OLDAPI, data);
+}
+
+/* Routines to get entropy from the OS. */
+#if defined(_WIN32)
+
+krb5_boolean
+k5_get_os_entropy(unsigned char *buf, size_t len, int strong)
+{
+ krb5_boolean result;
+ HCRYPTPROV provider;
+
+ /* CryptGenRandom is always considered strong. */
+
+ if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ return FALSE;
+ result = CryptGenRandom(provider, len, buf);
+ (void)CryptReleaseContext(provider, 0);
+ return result;
+}
+
+#else /* not Windows */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef __linux__
+#include <sys/syscall.h>
+#endif /* __linux__ */
+
+/* Open device, ensure that it is not a regular file, and read entropy. Return
+ * true on success, false on failure. */
+static krb5_boolean
+read_entropy_from_device(const char *device, unsigned char *buf, size_t len)
+{
+ struct stat sb;
+ int fd;
+ unsigned char *bp;
+ size_t left;
+ ssize_t count;
+ krb5_boolean result = FALSE;
+
+ fd = open(device, O_RDONLY);
+ if (fd == -1)
+ return FALSE;
+ set_cloexec_fd(fd);
+ if (fstat(fd, &sb) == -1 || S_ISREG(sb.st_mode))
+ goto cleanup;
+
+ for (bp = buf, left = len; left > 0;) {
+ count = read(fd, bp, left);
+ if (count <= 0)
+ goto cleanup;
+ left -= count;
+ bp += count;
+ }
+ result = TRUE;
+
+cleanup:
+ close(fd);
+ return result;
+}
+
+krb5_boolean
+k5_get_os_entropy(unsigned char *buf, size_t len, int strong)
+{
+ const char *device;
+#if defined(__linux__) && defined(SYS_getrandom)
+ int r;
+
+ while (len > 0) {
+ /*
+ * Pull from the /dev/urandom pool, but require it to have been seeded.
+ * This ensures strong randomness while only blocking during first
+ * system boot.
+ *
+ * glibc does not currently provide a binding for getrandom:
+ * https://sourceware.org/bugzilla/show_bug.cgi?id=17252
+ */
+ errno = 0;
+ r = syscall(SYS_getrandom, buf, len, 0);
+ if (r <= 0) {
+ if (errno == EINTR)
+ continue;
+
+ /* ENOSYS or other unrecoverable failure */
+ break;
+ }
+ len -= r;
+ buf += r;
+ }
+ if (len == 0)
+ return TRUE;
+#endif /* defined(__linux__) && defined(SYS_getrandom) */
+
+ device = strong ? "/dev/random" : "/dev/urandom";
+ return read_entropy_from_device(device, buf, len);
+}
+
+#endif /* not Windows */
diff --git a/src/lib/crypto/krb/prng_device.c b/src/lib/crypto/krb/prng_device.c
new file mode 100644
index 000000000000..bef5b3752416
--- /dev/null
+++ b/src/lib/crypto/krb/prng_device.c
@@ -0,0 +1,99 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/prng_device.c - OS device-based PRNG implementation */
+/*
+ * Copyright (C) 2011 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This file implements a PRNG module which relies on the system's /dev/urandom
+ * device. An OS packager can select this module given sufficient confidence
+ * in the operating system's native PRNG quality.
+ */
+
+#include "crypto_int.h"
+
+#define DEVICE "/dev/urandom"
+
+static int fd = -1;
+
+int
+k5_prng_init(void)
+{
+ /* Try to open the random device read-write; if that fails, read-only is
+ * okay. */
+ fd = open(DEVICE, O_RDWR, 0);
+ if (fd == -1)
+ fd = open(DEVICE, O_RDONLY, 0);
+ if (fd == -1)
+ return errno;
+ return 0;
+}
+
+void
+k5_prng_cleanup(void)
+{
+ close(fd);
+ fd = -1;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_add_entropy(krb5_context context, unsigned int randsource,
+ const krb5_data *indata)
+{
+ krb5_error_code ret;
+
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+
+ /* Some random devices let user-space processes contribute entropy. Don't
+ * worry if this fails. */
+ (void)write(fd, indata->data, indata->length);
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_make_octets(krb5_context context, krb5_data *outdata)
+{
+ char *buf = outdata->data;
+ size_t len = outdata->length;
+ ssize_t count;
+
+ while (len > 0) {
+ count = read(fd, buf, len);
+ if (count == 0) /* Not expected from a random device. */
+ return KRB5_CRYPTO_INTERNAL;
+ if (count == -1)
+ return errno;
+ buf += count;
+ len -= count;
+ }
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_os_entropy(krb5_context context, int strong, int *success)
+{
+ return 0;
+}
diff --git a/src/lib/crypto/krb/prng_fortuna.c b/src/lib/crypto/krb/prng_fortuna.c
new file mode 100644
index 000000000000..017a119cc460
--- /dev/null
+++ b/src/lib/crypto/krb/prng_fortuna.c
@@ -0,0 +1,470 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/prng_fortuna.c - Fortuna PRNG implementation */
+/*
+ * Copyright (c) 2005 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright (C) 2010, 2011 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This file implements the generator and accumulator parts of the Fortuna PRNG
+ * as described in chapter 9 of _Cryptography Engineering_ by Ferguson,
+ * Schneier, and Kohno.
+ *
+ * The generator, once seeded with an unguessable value, produces an unlimited
+ * number of pseudo-random outputs which cannot be used to determine the
+ * internal state of the generator (without an unreasonable amount of
+ * computational power). The generator protects against the case where the OS
+ * random number generator is not cryptographically secure, but can produce an
+ * unguessable initial seed. Successive reseeds of the generator will not make
+ * the internal state any more guessable than it was before.
+ *
+ * The accumulator is layered on top of the generator, and seeks to eventually
+ * recover from the case where the OS random number generator did not produce
+ * an unguessable initial seed. Unreliable entropy inputs are collected into
+ * 32 pools, which are used to reseed the generator when enough entropy has
+ * been collected. Each pool collects twice as much entropy between reseeds as
+ * the previous one; eventually a reseed will occur involving a pool with
+ * enough entropy that an attacker cannot maintain knowledge of the generator's
+ * internal state. The accumulator is only helpful for a long-running process
+ * such as a KDC which can submit periodic entropy inputs to the PRNG.
+ */
+
+#include "crypto_int.h"
+
+/* The accumulator's number of pools. */
+#define NUM_POOLS 32
+
+/* Minimum reseed interval in microseconds. */
+#define RESEED_INTERVAL 100000 /* 0.1 sec */
+
+/* For one big request, change the key after this many bytes. */
+#define MAX_BYTES_PER_KEY (1 << 20)
+
+/* Reseed if pool 0 has had this many bytes added since last reseed. */
+#define MIN_POOL_LEN 64
+
+/* AES-256 key size in bytes. */
+#define AES256_KEYSIZE (256/8)
+
+/* AES-256 block size in bytes. */
+#define AES256_BLOCKSIZE (128/8)
+
+/* SHA-256 block size in bytes. */
+#define SHA256_BLOCKSIZE (512/8)
+
+/* SHA-256 result size in bytes. */
+#define SHA256_HASHSIZE (256/8)
+
+/* Genarator - block cipher in CTR mode */
+struct fortuna_state
+{
+ /* Generator state. */
+ unsigned char counter[AES256_BLOCKSIZE];
+ unsigned char key[AES256_KEYSIZE];
+ aes_ctx ciph;
+
+ /* Accumulator state. */
+ SHA256_CTX pool[NUM_POOLS];
+ unsigned int pool_index;
+ unsigned int reseed_count;
+ struct timeval last_reseed_time;
+ unsigned int pool0_bytes;
+};
+
+/*
+ * SHA[d]-256(m) is defined as SHA-256(SHA-256(0^512||m))--that is, hash a
+ * block full of zeros followed by the input data, then re-hash the result.
+ * These functions implement the SHA[d]-256 function on incremental inputs.
+ */
+
+static void
+shad256_init(SHA256_CTX *ctx)
+{
+ unsigned char zero[SHA256_BLOCKSIZE];
+
+ /* Initialize the inner SHA-256 context and update it with a zero block. */
+ memset(zero, 0, sizeof(zero));
+ k5_sha256_init(ctx);
+ k5_sha256_update(ctx, zero, sizeof(zero));
+}
+
+static void
+shad256_update(SHA256_CTX *ctx, const unsigned char *data, int len)
+{
+ /* Feed the input to the inner SHA-256 context. */
+ k5_sha256_update(ctx, data, len);
+}
+
+static void
+shad256_result(SHA256_CTX *ctx, unsigned char *dst)
+{
+ /* Finalize the inner context, then feed the result back through SHA256. */
+ k5_sha256_final(dst, ctx);
+ k5_sha256_init(ctx);
+ k5_sha256_update(ctx, dst, SHA256_HASHSIZE);
+ k5_sha256_final(dst, ctx);
+}
+
+/* Initialize state. */
+static void
+init_state(struct fortuna_state *st)
+{
+ unsigned int i;
+
+ memset(st, 0, sizeof(*st));
+ for (i = 0; i < NUM_POOLS; i++)
+ shad256_init(&st->pool[i]);
+}
+
+/* Increment st->counter using least significant byte first. */
+static void
+inc_counter(struct fortuna_state *st)
+{
+ uint64_t val;
+
+ val = load_64_le(st->counter) + 1;
+ store_64_le(val, st->counter);
+ if (val == 0) {
+ val = load_64_le(st->counter + 8) + 1;
+ store_64_le(val, st->counter + 8);
+ }
+}
+
+/* Encrypt and increment st->counter in the current cipher context. */
+static void
+encrypt_counter(struct fortuna_state *st, unsigned char *dst)
+{
+ krb5int_aes_enc_blk(st->counter, dst, &st->ciph);
+ inc_counter(st);
+}
+
+/* Reseed the generator based on hopefully non-guessable input. */
+static void
+generator_reseed(struct fortuna_state *st, const unsigned char *data,
+ size_t len)
+{
+ SHA256_CTX ctx;
+
+ /* Calculate SHA[d]-256(key||s) and make that the new key. Depend on the
+ * SHA-256 hash size being the AES-256 key size. */
+ shad256_init(&ctx);
+ shad256_update(&ctx, st->key, AES256_KEYSIZE);
+ shad256_update(&ctx, data, len);
+ shad256_result(&ctx, st->key);
+ zap(&ctx, sizeof(ctx));
+ krb5int_aes_enc_key(st->key, AES256_KEYSIZE, &st->ciph);
+
+ /* Increment counter. */
+ inc_counter(st);
+}
+
+/* Generate two blocks in counter mode and replace the key with the result. */
+static void
+change_key(struct fortuna_state *st)
+{
+ encrypt_counter(st, st->key);
+ encrypt_counter(st, st->key + AES256_BLOCKSIZE);
+ krb5int_aes_enc_key(st->key, AES256_KEYSIZE, &st->ciph);
+}
+
+/* Output pseudo-random data from the generator. */
+static void
+generator_output(struct fortuna_state *st, unsigned char *dst, size_t len)
+{
+ unsigned char result[AES256_BLOCKSIZE];
+ size_t n, count = 0;
+
+ while (len > 0) {
+ /* Produce bytes and copy the result into dst. */
+ encrypt_counter(st, result);
+ n = (len < AES256_BLOCKSIZE) ? len : AES256_BLOCKSIZE;
+ memcpy(dst, result, n);
+ dst += n;
+ len -= n;
+
+ /* Each time we reach MAX_BYTES_PER_KEY bytes, change the key. */
+ count += AES256_BLOCKSIZE;
+ if (count >= MAX_BYTES_PER_KEY) {
+ change_key(st);
+ count = 0;
+ }
+ }
+ zap(result, sizeof(result));
+
+ /* Change the key after each request. */
+ change_key(st);
+}
+
+/* Reseed the generator using the accumulator pools. */
+static void
+accumulator_reseed(struct fortuna_state *st)
+{
+ unsigned int i, n;
+ SHA256_CTX ctx;
+ unsigned char hash_result[SHA256_HASHSIZE];
+
+ n = ++st->reseed_count;
+
+ /*
+ * Collect entropy from pools. We use the i-th pool only 1/(2^i) of the
+ * time so that each pool collects twice as much entropy between uses as
+ * the last.
+ */
+ shad256_init(&ctx);
+ for (i = 0; i < NUM_POOLS; i++) {
+ if (n % (1 << i) != 0)
+ break;
+
+ /* Harvest this pool's hash result into ctx, then reset the pool. */
+ shad256_result(&st->pool[i], hash_result);
+ shad256_init(&st->pool[i]);
+ shad256_update(&ctx, hash_result, SHA256_HASHSIZE);
+ }
+ shad256_result(&ctx, hash_result);
+ generator_reseed(st, hash_result, SHA256_HASHSIZE);
+ zap(hash_result, SHA256_HASHSIZE);
+ zap(&ctx, sizeof(ctx));
+
+ /* Reset the count of bytes added to pool 0. */
+ st->pool0_bytes = 0;
+}
+
+/* Add possibly unguessable data to the next accumulator pool. */
+static void
+accumulator_add_event(struct fortuna_state *st, const unsigned char *data,
+ size_t len)
+{
+ unsigned char lenbuf[2];
+ SHA256_CTX *pool;
+
+ /* Track how many bytes have been added to pool 0. */
+ if (st->pool_index == 0 && st->pool0_bytes < MIN_POOL_LEN)
+ st->pool0_bytes += len;
+
+ /* Hash events into successive accumulator pools. */
+ pool = &st->pool[st->pool_index];
+ st->pool_index = (st->pool_index + 1) % NUM_POOLS;
+
+ /*
+ * Fortuna specifies that events are encoded with a source identifier byte,
+ * a length byte, and the event data itself. We do not have source
+ * identifiers and they're not really important, so just encode the
+ * length in two bytes instead.
+ */
+ store_16_be(len, lenbuf);
+ shad256_update(pool, lenbuf, 2);
+ shad256_update(pool, data, len);
+}
+
+/* Limit dependencies for test program. */
+#ifndef TEST
+
+/* Return true if RESEED_INTERVAL microseconds have passed since the last
+ * reseed. */
+static krb5_boolean
+enough_time_passed(struct fortuna_state *st)
+{
+ struct timeval tv, *last = &st->last_reseed_time;
+ krb5_boolean ok = FALSE;
+
+ gettimeofday(&tv, NULL);
+
+ /* Check how much time has passed. */
+ if (tv.tv_sec > last->tv_sec + 1)
+ ok = TRUE;
+ else if (tv.tv_sec == last->tv_sec + 1) {
+ if (1000000 + tv.tv_usec - last->tv_usec >= RESEED_INTERVAL)
+ ok = TRUE;
+ } else if (tv.tv_usec - last->tv_usec >= RESEED_INTERVAL)
+ ok = TRUE;
+
+ /* Update last_reseed_time if we're returning success. */
+ if (ok)
+ memcpy(last, &tv, sizeof(tv));
+
+ return ok;
+}
+
+static void
+accumulator_output(struct fortuna_state *st, unsigned char *dst, size_t len)
+{
+ /* Reseed the generator with data from pools if we have accumulated enough
+ * data and enough time has passed since the last accumulator reseed. */
+ if (st->pool0_bytes >= MIN_POOL_LEN && enough_time_passed(st))
+ accumulator_reseed(st);
+
+ generator_output(st, dst, len);
+}
+
+static k5_mutex_t fortuna_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+static struct fortuna_state main_state;
+#ifdef _WIN32
+static DWORD last_pid;
+#else
+static pid_t last_pid;
+#endif
+static krb5_boolean have_entropy = FALSE;
+
+int
+k5_prng_init(void)
+{
+ krb5_error_code ret = 0;
+ unsigned char osbuf[64];
+
+ ret = k5_mutex_finish_init(&fortuna_lock);
+ if (ret)
+ return ret;
+
+ init_state(&main_state);
+#ifdef _WIN32
+ last_pid = GetCurrentProcessId();
+#else
+ last_pid = getpid();
+#endif
+ if (k5_get_os_entropy(osbuf, sizeof(osbuf), 0)) {
+ generator_reseed(&main_state, osbuf, sizeof(osbuf));
+ have_entropy = TRUE;
+ }
+
+ return 0;
+}
+
+void
+k5_prng_cleanup(void)
+{
+ have_entropy = FALSE;
+ zap(&main_state, sizeof(main_state));
+ k5_mutex_destroy(&fortuna_lock);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_add_entropy(krb5_context context, unsigned int randsource,
+ const krb5_data *indata)
+{
+ krb5_error_code ret;
+
+ ret = krb5int_crypto_init();
+ if (ret)
+ return ret;
+ k5_mutex_lock(&fortuna_lock);
+ if (randsource == KRB5_C_RANDSOURCE_OSRAND ||
+ randsource == KRB5_C_RANDSOURCE_TRUSTEDPARTY) {
+ /* These sources contain enough entropy that we should use them
+ * immediately, so that they benefit the next request. */
+ generator_reseed(&main_state, (unsigned char *)indata->data,
+ indata->length);
+ have_entropy = TRUE;
+ } else {
+ /* Other sources should just go into the pools and be used according to
+ * the accumulator logic. */
+ accumulator_add_event(&main_state, (unsigned char *)indata->data,
+ indata->length);
+ }
+ k5_mutex_unlock(&fortuna_lock);
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_make_octets(krb5_context context, krb5_data *outdata)
+{
+#ifdef _WIN32
+ DWORD pid = GetCurrentProcessId();
+#else
+ pid_t pid = getpid();
+#endif
+ unsigned char pidbuf[4];
+
+ k5_mutex_lock(&fortuna_lock);
+
+ if (!have_entropy) {
+ k5_mutex_unlock(&fortuna_lock);
+ if (context != NULL) {
+ k5_set_error(&context->err, KRB5_CRYPTO_INTERNAL,
+ _("Random number generator could not be seeded"));
+ }
+ return KRB5_CRYPTO_INTERNAL;
+ }
+
+ if (pid != last_pid) {
+ /* We forked; make sure child's PRNG stream differs from parent's. */
+ store_32_be(pid, pidbuf);
+ generator_reseed(&main_state, pidbuf, 4);
+ last_pid = pid;
+ }
+
+ accumulator_output(&main_state, (unsigned char *)outdata->data,
+ outdata->length);
+ k5_mutex_unlock(&fortuna_lock);
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_os_entropy(krb5_context context, int strong, int *success)
+{
+ krb5_error_code ret;
+ krb5_data data;
+ uint8_t buf[64];
+ int status = 0;
+
+ if (!k5_get_os_entropy(buf, sizeof(buf), strong))
+ goto done;
+
+ data = make_data(buf, sizeof(buf));
+ ret = krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_OSRAND, &data);
+ if (ret)
+ goto done;
+
+ status = 1;
+
+done:
+ if (success != NULL)
+ *success = status;
+ return 0;
+}
+
+#endif /* not TEST */
diff --git a/src/lib/crypto/krb/prng_os.c b/src/lib/crypto/krb/prng_os.c
new file mode 100644
index 000000000000..8ea13e7fc1dd
--- /dev/null
+++ b/src/lib/crypto/krb/prng_os.c
@@ -0,0 +1,72 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/prng_os.c - OS PRNG implementation */
+/*
+ * Copyright (C) 2016 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file implements a PRNG module which relies on the system's PRNG. An
+ * OS packager can select this module given sufficient confidence in the
+ * operating system's native PRNG quality.
+ */
+
+#include "crypto_int.h"
+
+int
+k5_prng_init(void)
+{
+ return 0;
+}
+
+void
+k5_prng_cleanup(void)
+{
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_add_entropy(krb5_context context, unsigned int randsource,
+ const krb5_data *indata)
+{
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_make_octets(krb5_context context, krb5_data *outdata)
+{
+ krb5_boolean res;
+
+ res = k5_get_os_entropy((uint8_t *)outdata->data, outdata->length, 0);
+ return res ? 0 : KRB5_CRYPTO_INTERNAL;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_os_entropy(krb5_context context, int strong, int *success)
+{
+ return 0;
+}
diff --git a/src/lib/crypto/krb/random_to_key.c b/src/lib/crypto/krb/random_to_key.c
new file mode 100644
index 000000000000..1574625268c9
--- /dev/null
+++ b/src/lib/crypto/krb/random_to_key.c
@@ -0,0 +1,118 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * COPYRIGHT (c) 2006
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+/*
+ * Create a key given random data. It is assumed that random_key has
+ * already been initialized and random_key->contents have been allocated
+ * with the correct length.
+ */
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_to_key(krb5_context context, krb5_enctype enctype,
+ krb5_data *random_data, krb5_keyblock *random_key)
+{
+ krb5_error_code ret;
+ const struct krb5_keytypes *ktp;
+
+ if (random_data == NULL || random_key == NULL ||
+ random_key->contents == NULL)
+ return EINVAL;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ if (random_key->length != ktp->enc->keylength)
+ return KRB5_BAD_KEYSIZE;
+
+ ret = ktp->rand2key(random_data, random_key);
+ if (ret)
+ zap(random_key->contents, random_key->length);
+
+ return ret;
+}
+
+krb5_error_code
+k5_rand2key_direct(const krb5_data *randombits, krb5_keyblock *keyblock)
+{
+ if (randombits->length != keyblock->length)
+ return KRB5_CRYPTO_INTERNAL;
+
+ keyblock->magic = KV5M_KEYBLOCK;
+ memcpy(keyblock->contents, randombits->data, randombits->length);
+ return 0;
+}
+
+static inline void
+eighth_byte(unsigned char *b)
+{
+ b[7] = (((b[0] & 1) << 1) | ((b[1] & 1) << 2) | ((b[2] & 1) << 3) |
+ ((b[3] & 1) << 4) | ((b[4] & 1) << 5) | ((b[5] & 1) << 6) |
+ ((b[6] & 1) << 7));
+}
+
+krb5_error_code
+k5_rand2key_des(const krb5_data *randombits, krb5_keyblock *keyblock)
+{
+ if (randombits->length != 7)
+ return(KRB5_CRYPTO_INTERNAL);
+
+ keyblock->magic = KV5M_KEYBLOCK;
+
+ /* Take the seven bytes, move them around into the top 7 bits of the
+ * 8 key bytes, then compute the parity bits. */
+ memcpy(keyblock->contents, randombits->data, randombits->length);
+ eighth_byte(keyblock->contents);
+ k5_des_fixup_key_parity(keyblock->contents);
+
+ return 0;
+}
+
+krb5_error_code
+k5_rand2key_des3(const krb5_data *randombits, krb5_keyblock *keyblock)
+{
+ int i;
+
+ if (randombits->length != 21)
+ return KRB5_CRYPTO_INTERNAL;
+
+ keyblock->magic = KV5M_KEYBLOCK;
+
+ /* 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(&keyblock->contents[i * 8], &randombits->data[i * 7], 7);
+ eighth_byte(&keyblock->contents[i * 8]);
+ k5_des_fixup_key_parity(&keyblock->contents[i * 8]);
+ }
+ return 0;
+}
diff --git a/src/lib/crypto/krb/s2k_des.c b/src/lib/crypto/krb/s2k_des.c
new file mode 100644
index 000000000000..31a613bebc61
--- /dev/null
+++ b/src/lib/crypto/krb/s2k_des.c
@@ -0,0 +1,691 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * RFC 3961 and AFS string to key. These are not standard crypto primitives
+ * (RFC 3961 string-to-key is implemented in OpenSSL for historical reasons but
+ * it doesn't get weak keys right), so we have to implement them here.
+ */
+
+#include <ctype.h>
+#include "crypto_int.h"
+
+#undef min
+#define min(a,b) ((a)>(b)?(b):(a))
+
+/* Compute a CBC checksum of in (with length len) using the specified key and
+ * ivec. The result is written into out. */
+static krb5_error_code
+des_cbc_mac(const unsigned char *keybits, const unsigned char *ivec,
+ const unsigned char *in, size_t len, unsigned char *out)
+{
+ krb5_error_code ret;
+ krb5_keyblock kb;
+ krb5_key key;
+ krb5_crypto_iov iov[2];
+ unsigned char zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ krb5_data outd, ivecd;
+
+ /* Make a key from keybits. */
+ kb.magic = KV5M_KEYBLOCK;
+ kb.enctype = ENCTYPE_DES_CBC_CRC;
+ kb.length = 8;
+ kb.contents = (unsigned char *)keybits;
+ ret = krb5_k_create_key(NULL, &kb, &key);
+ if (ret)
+ return ret;
+
+ /* Make iovs for the input data, padding it out to the block size. */
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[0].data = make_data((unsigned char *)in, len);
+ iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[1].data = make_data(zero, krb5_roundup(len, 8) - len);
+
+ /* Make krb5_data structures for the ivec and output. */
+ ivecd = make_data((unsigned char *)ivec, 8);
+ outd = make_data(out, 8);
+
+ /* Call the cbc_mac operation of the module's DES enc-provider. */
+ ret = krb5int_enc_des.cbc_mac(key, iov, 2, &ivecd, &outd);
+ krb5_k_free_key(NULL, key);
+ return ret;
+}
+
+/*** AFS string-to-key constants ***/
+
+/* 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},
+};
+
+
+/* Set up the key schedule from the key. */
+static void
+afs_crypt_setkey(char *key, char *E, char (*KS)[48])
+{
+ int i, j, k, t;
+ char C[28], D[28]; /* Used to calculate key schedule. */
+
+ /*
+ * 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];
+ }
+ }
+
+ memcpy(E, e, 48);
+}
+
+/*
+ * The payoff: encrypt a block.
+ */
+
+static void
+afs_encrypt_block(char *block, char *E, char (*KS)[48])
+{
+ const long edflag = 0;
+ int i, ii;
+ int t, j, k;
+ char tempL[32];
+ char f[32];
+ char L[64]; /* Current block divided into two halves */
+ 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. */
+ i = (edflag) ? 15 - ii : ii;
+ /* Save the R array, which will be the new L. */
+ memcpy(tempL, R, 32);
+ /* 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) & 1;
+ f[t + 1] = (k >> 2) & 1;
+ f[t + 2] = (k >> 1) & 1;
+ f[t + 3] = (k >> 0) & 1;
+ }
+ /* 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. */
+ memcpy(L, tempL, 32);
+ }
+ /* 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];
+}
+
+/* iobuf must be at least 16 bytes */
+static char *
+afs_crypt(const char *pw, const char *salt, char *iobuf)
+{
+ int i, j, c;
+ int temp;
+ char block[66];
+ char E[48];
+ char KS[16][48]; /* Key schedule, generated from key */
+
+ for (i = 0; i < 66; i++)
+ block[i] = 0;
+ for (i = 0; (c = *pw) != '\0' && i < 64; pw++){
+ for(j = 0; j < 7; j++, i++)
+ block[i] = (c >> (6 - j)) & 01;
+ i++;
+ }
+
+ 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++)
+ afs_encrypt_block(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;
+}
+
+static krb5_error_code
+afs_s2k_oneblock(const krb5_data *data, const krb5_data *salt,
+ unsigned char *key_out)
+{
+ unsigned int i;
+ unsigned char password[9]; /* trailing nul for crypt() */
+ char afs_crypt_buf[16];
+
+ /*
+ * 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.
+ */
+
+ memset(password, 0, sizeof(password));
+ if (salt->length > 0)
+ memcpy(password, salt->data, 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_out,
+ (char *)afs_crypt((char *)password, "#~", afs_crypt_buf) + 2, 8);
+ for (i = 0; i < 8; i++)
+ key_out[i] <<= 1;
+ /* Fix up key parity again. */
+ k5_des_fixup_key_parity(key_out);
+ zap(password, sizeof(password));
+ return 0;
+}
+
+static krb5_error_code
+afs_s2k_multiblock(const krb5_data *data, const krb5_data *salt,
+ unsigned char *key_out)
+{
+ krb5_error_code ret;
+ unsigned char ivec[8], tkey[8], *password;
+ size_t pw_len = salt->length + data->length;
+ unsigned int i, j;
+
+ /* Do a CBC checksum, twice, and use the result as the new key. */
+
+ password = malloc(pw_len);
+ if (!password)
+ return ENOMEM;
+
+ if (data->length > 0)
+ memcpy(password, data->data, data->length);
+ for (i = data->length, j = 0; j < salt->length; i++, j++) {
+ password[i] = salt->data[j];
+ if (isupper(password[i]))
+ password[i] = tolower(password[i]);
+ }
+
+ memcpy(ivec, "kerberos", sizeof(ivec));
+ memcpy(tkey, ivec, sizeof(tkey));
+ k5_des_fixup_key_parity(tkey);
+ ret = des_cbc_mac(tkey, ivec, password, pw_len, tkey);
+ if (ret)
+ goto cleanup;
+
+ memcpy(ivec, tkey, sizeof(ivec));
+ k5_des_fixup_key_parity(tkey);
+ ret = des_cbc_mac(tkey, ivec, password, pw_len, key_out);
+ if (ret)
+ goto cleanup;
+ k5_des_fixup_key_parity(key_out);
+
+cleanup:
+ zapfree(password, pw_len);
+ return ret;
+}
+
+static krb5_error_code
+afs_s2k(const krb5_data *data, const krb5_data *salt, unsigned char *key_out)
+{
+ if (data->length <= 8)
+ return afs_s2k_oneblock(data, salt, key_out);
+ else
+ return afs_s2k_multiblock(data, salt, key_out);
+}
+
+static krb5_error_code
+des_s2k(const krb5_data *pw, const krb5_data *salt, unsigned char *key_out)
+{
+ union {
+ /* 8 "forward" bytes, 8 "reverse" bytes */
+ unsigned char uc[16];
+ krb5_ui_4 ui[4];
+ } temp;
+ unsigned int i;
+ krb5_ui_4 x, y, z;
+ unsigned char *p, *copy;
+ size_t copylen;
+ krb5_error_code ret;
+
+ /* 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
+
+ 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;
+ if (pw->length > 0)
+ memcpy(copy, pw->data, pw->length);
+ if (salt != NULL && salt->length > 0)
+ 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
+#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; \
+ }
+
+ 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) (k5_des_fixup_key_parity(k), \
+ k5_des_is_weak_key(k) ? (k[7] ^= 0xF0) : 0)
+
+ /* Now temp.cb is the temporary key, with invalid parity. */
+ FIXUP(temp.uc);
+
+#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
+
+ ret = des_cbc_mac(temp.uc, temp.uc, copy, copylen, temp.uc);
+ if (ret)
+ goto cleanup;
+
+#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
+
+ FIXUP(temp.uc);
+
+#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_out, temp.uc, 8);
+
+cleanup:
+ zap(&temp, sizeof(temp));
+ zapfree(copy, copylen);
+ return ret;
+}
+
+krb5_error_code
+krb5int_des_string_to_key(const struct krb5_keytypes *ktp,
+ const krb5_data *string, const krb5_data *salt,
+ const krb5_data *parm, krb5_keyblock *keyblock)
+{
+ int type;
+
+ if (parm != NULL) {
+ if (parm->length != 1)
+ return KRB5_ERR_BAD_S2K_PARAMS;
+ type = parm->data[0];
+ if (type != 0 && type != 1)
+ return KRB5_ERR_BAD_S2K_PARAMS;
+ } else
+ type = 0;
+
+ /* Use AFS string to key if we were told to. */
+ if (type == 1)
+ return afs_s2k(string, salt, keyblock->contents);
+
+ return des_s2k(string, salt, keyblock->contents);
+}
diff --git a/src/lib/crypto/krb/s2k_pbkdf2.c b/src/lib/crypto/krb/s2k_pbkdf2.c
new file mode 100644
index 000000000000..ec5856c2be79
--- /dev/null
+++ b/src/lib/crypto/krb/s2k_pbkdf2.c
@@ -0,0 +1,216 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+static const unsigned char kerberos[] = "kerberos";
+#define kerberos_len (sizeof(kerberos)-1)
+
+krb5_error_code
+krb5int_dk_string_to_key(const struct krb5_keytypes *ktp,
+ const krb5_data *string, const krb5_data *salt,
+ const krb5_data *parms, krb5_keyblock *keyblock)
+{
+ krb5_error_code ret;
+ size_t keybytes, keylength, concatlen;
+ unsigned char *concat = NULL, *foldstring = NULL, *foldkeydata = NULL;
+ krb5_data indata;
+ krb5_keyblock foldkeyblock;
+ krb5_key foldkey = NULL;
+
+ /* keyblock->length is checked by krb5int_derive_key. */
+
+ keybytes = ktp->enc->keybytes;
+ keylength = ktp->enc->keylength;
+
+ concatlen = string->length + (salt ? salt->length : 0);
+
+ concat = k5alloc(concatlen, &ret);
+ if (ret != 0)
+ goto cleanup;
+ foldstring = k5alloc(keybytes, &ret);
+ if (ret != 0)
+ goto cleanup;
+ foldkeydata = k5alloc(keylength, &ret);
+ if (ret != 0)
+ goto cleanup;
+
+ /* construct input string ( = string + salt), fold it, make_key it */
+
+ if (string->length > 0)
+ memcpy(concat, string->data, string->length);
+ if (salt != NULL && salt->length > 0)
+ memcpy(concat + string->length, salt->data, salt->length);
+
+ krb5int_nfold(concatlen*8, concat, keybytes*8, foldstring);
+
+ indata.length = keybytes;
+ indata.data = (char *) foldstring;
+ foldkeyblock.length = keylength;
+ foldkeyblock.contents = foldkeydata;
+ foldkeyblock.enctype = ktp->etype;
+
+ ret = ktp->rand2key(&indata, &foldkeyblock);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = krb5_k_create_key(NULL, &foldkeyblock, &foldkey);
+ if (ret != 0)
+ goto cleanup;
+
+ /* now derive the key from this one */
+
+ indata.length = kerberos_len;
+ indata.data = (char *) kerberos;
+
+ ret = krb5int_derive_keyblock(ktp->enc, NULL, foldkey, keyblock, &indata,
+ DERIVE_RFC3961);
+ if (ret != 0)
+ memset(keyblock->contents, 0, keyblock->length);
+
+cleanup:
+ zapfree(concat, concatlen);
+ zapfree(foldstring, keybytes);
+ zapfree(foldkeydata, keylength);
+ krb5_k_free_key(NULL, foldkey);
+ return ret;
+}
+
+
+#define MAX_ITERATION_COUNT 0x1000000L
+
+krb5_boolean k5_allow_weak_pbkdf2iter = FALSE;
+
+static krb5_error_code
+pbkdf2_string_to_key(const struct krb5_keytypes *ktp, const krb5_data *string,
+ const krb5_data *salt, const krb5_data *pepper,
+ const krb5_data *params, krb5_keyblock *key,
+ enum deriv_alg deriv_alg, unsigned long def_iter_count)
+{
+ const struct krb5_hash_provider *hash;
+ unsigned long iter_count;
+ krb5_data out;
+ static const krb5_data usage = { KV5M_DATA, 8, "kerberos" };
+ krb5_key tempkey = NULL;
+ krb5_error_code err;
+ krb5_data sandp = empty_data();
+
+ if (params) {
+ unsigned char *p = (unsigned char *) params->data;
+ if (params->length != 4)
+ return KRB5_ERR_BAD_S2K_PARAMS;
+ iter_count = load_32_be(p);
+ /* Zero means 2^32, which is way above what we will accept. Also don't
+ * accept values less than the default, unless we're running tests. */
+ if (iter_count == 0 ||
+ (!k5_allow_weak_pbkdf2iter && iter_count < def_iter_count))
+ return KRB5_ERR_BAD_S2K_PARAMS;
+
+ } else
+ iter_count = def_iter_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;
+
+ /* Use the output keyblock contents for temporary space. */
+ out.data = (char *) key->contents;
+ out.length = key->length;
+ if (out.length != 16 && out.length != 32)
+ return KRB5_CRYPTO_INTERNAL;
+
+ if (pepper != NULL) {
+ err = alloc_data(&sandp, pepper->length + 1 + salt->length);
+ if (err)
+ return err;
+
+ if (pepper->length > 0)
+ memcpy(sandp.data, pepper->data, pepper->length);
+ sandp.data[pepper->length] = '\0';
+ if (salt->length > 0)
+ memcpy(&sandp.data[pepper->length + 1], salt->data, salt->length);
+
+ salt = &sandp;
+ }
+
+ hash = (ktp->hash != NULL) ? ktp->hash : &krb5int_hash_sha1;
+ err = krb5int_pbkdf2_hmac(hash, &out, iter_count, string, salt);
+ if (err)
+ goto cleanup;
+
+ err = krb5_k_create_key (NULL, key, &tempkey);
+ if (err)
+ goto cleanup;
+
+ err = krb5int_derive_keyblock(ktp->enc, ktp->hash, tempkey, key, &usage,
+ deriv_alg);
+
+cleanup:
+ if (sandp.data)
+ free(sandp.data);
+ if (err)
+ memset (out.data, 0, out.length);
+ krb5_k_free_key (NULL, tempkey);
+ return err;
+}
+
+krb5_error_code
+krb5int_aes_string_to_key(const struct krb5_keytypes *ktp,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key)
+{
+ return pbkdf2_string_to_key(ktp, string, salt, NULL, params, key,
+ DERIVE_RFC3961, 4096);
+}
+
+krb5_error_code
+krb5int_camellia_string_to_key(const struct krb5_keytypes *ktp,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key)
+{
+ krb5_data pepper = string2data(ktp->name);
+
+ return pbkdf2_string_to_key(ktp, string, salt, &pepper, params, key,
+ DERIVE_SP800_108_CMAC, 32768);
+}
+
+krb5_error_code
+krb5int_aes2_string_to_key(const struct krb5_keytypes *ktp,
+ const krb5_data *string, const krb5_data *salt,
+ const krb5_data *params, krb5_keyblock *key)
+{
+ krb5_data pepper = string2data(ktp->name);
+
+ return pbkdf2_string_to_key(ktp, string, salt, &pepper, params, key,
+ DERIVE_SP800_108_HMAC, 32768);
+}
diff --git a/src/lib/crypto/krb/s2k_rc4.c b/src/lib/crypto/krb/s2k_rc4.c
new file mode 100644
index 000000000000..49ad89d323b0
--- /dev/null
+++ b/src/lib/crypto/krb/s2k_rc4.c
@@ -0,0 +1,37 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#include "crypto_int.h"
+#include "k5-utf8.h"
+
+krb5_error_code
+krb5int_arcfour_string_to_key(const struct krb5_keytypes *ktp,
+ const krb5_data *string, const krb5_data *salt,
+ const krb5_data *params, krb5_keyblock *key)
+{
+ krb5_error_code err = 0;
+ krb5_crypto_iov iov;
+ krb5_data hash_out;
+ 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. */
+ err = krb5int_utf8cs_to_ucs2les(string->data, string->length, &copystr,
+ &copystrlen);
+ if (err)
+ return err;
+
+ /* the actual MD4 hash of the data */
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = make_data(copystr, copystrlen);
+ hash_out = make_data(key->contents, key->length);
+ err = krb5int_hash_md4.hash(&iov, 1, &hash_out);
+
+ /* Zero out the data behind us */
+ zapfree(copystr, copystrlen);
+ return err;
+}
diff --git a/src/lib/crypto/krb/state.c b/src/lib/crypto/krb/state.c
new file mode 100644
index 000000000000..a7fb020b2f6d
--- /dev/null
+++ b/src/lib/crypto/krb/state.c
@@ -0,0 +1,60 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/state.c */
+/*
+ * Copyright (C) 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
+
+ *
+ *
+ *
+ * * Section 6 (Encryption) of the Kerberos revisions document defines
+ * cipher states to be used to chain encryptions and decryptions
+ * together. Examples of cipher states include initialization vectors
+ * for CBC encription. This file contains implementations of
+ * krb5_c_init_state and krb5_c_free_state used by clients of the
+ * Kerberos crypto library.
+ */
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_init_state (krb5_context context, const krb5_keyblock *key,
+ krb5_keyusage keyusage, krb5_data *new_state)
+{
+ const struct krb5_keytypes *ktp;
+
+ ktp = find_enctype(key->enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ return ktp->enc->init_state(key, keyusage, new_state);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_free_state(krb5_context context, const krb5_keyblock *key,
+ krb5_data *state)
+{
+ const struct krb5_keytypes *ktp;
+
+ ktp = find_enctype(key->enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ ktp->enc->free_state(state);
+ return 0;
+}
diff --git a/src/lib/crypto/krb/string_to_cksumtype.c b/src/lib/crypto/krb/string_to_cksumtype.c
new file mode 100644
index 000000000000..3498d2a0539d
--- /dev/null
+++ b/src/lib/crypto/krb/string_to_cksumtype.c
@@ -0,0 +1,56 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_string_to_cksumtype(char *string, krb5_cksumtype *cksumtypep)
+{
+ unsigned int i, j;
+ const char *alias;
+ const struct krb5_cksumtypes *ctp;
+
+ for (i=0; i<krb5int_cksumtypes_length; i++) {
+ ctp = &krb5int_cksumtypes_list[i];
+ if (strcasecmp(ctp->name, string) == 0) {
+ *cksumtypep = ctp->ctype;
+ return 0;
+ }
+#define MAX_ALIASES (sizeof(ctp->aliases) / sizeof(ctp->aliases[0]))
+ for (j = 0; j < MAX_ALIASES; j++) {
+ alias = ctp->aliases[j];
+ if (alias == NULL)
+ break;
+ if (strcasecmp(alias, string) == 0) {
+ *cksumtypep = ctp->ctype;
+ return 0;
+ }
+ }
+ }
+
+ return EINVAL;
+}
diff --git a/src/lib/crypto/krb/string_to_key.c b/src/lib/crypto/krb/string_to_key.c
new file mode 100644
index 000000000000..b55ee75d2f34
--- /dev/null
+++ b/src/lib/crypto/krb/string_to_key.c
@@ -0,0 +1,74 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_string_to_key(krb5_context context, krb5_enctype enctype,
+ const krb5_data *string, const krb5_data *salt,
+ krb5_keyblock *key)
+{
+ return krb5_c_string_to_key_with_params(context, enctype, string, salt,
+ NULL, key);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params, krb5_keyblock *key)
+{
+ krb5_error_code ret;
+ const struct krb5_keytypes *ktp;
+ size_t keylength;
+
+ ktp = find_enctype(enctype);
+ if (ktp == NULL)
+ return KRB5_BAD_ENCTYPE;
+ keylength = ktp->enc->keylength;
+
+ /* Fail gracefully if someone is using the old AFS string-to-key hack. */
+ if (salt != NULL && salt->length == SALT_TYPE_AFS_LENGTH)
+ return EINVAL;
+
+ key->contents = malloc(keylength);
+ if (key->contents == NULL)
+ return ENOMEM;
+
+ key->magic = KV5M_KEYBLOCK;
+ key->enctype = enctype;
+ key->length = keylength;
+
+ ret = (*ktp->str2key)(ktp, string, salt, params, key);
+ if (ret) {
+ zapfree(key->contents, keylength);
+ key->length = 0;
+ key->contents = NULL;
+ }
+
+ return ret;
+}
diff --git a/src/lib/crypto/krb/t_fortuna.c b/src/lib/crypto/krb/t_fortuna.c
new file mode 100644
index 000000000000..4f25bee62cb5
--- /dev/null
+++ b/src/lib/crypto/krb/t_fortuna.c
@@ -0,0 +1,179 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/t_fortuna.c - Fortuna test program */
+/*
+ * Copyright (c) 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright (C) 2011 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-int.h"
+#ifdef FORTUNA
+
+/* Include most of prng_fortuna.c so we can test the PRNG internals. */
+#define TEST
+#include "prng_fortuna.c"
+
+static void
+display(const unsigned char *data, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++)
+ printf("%02X", data[i]);
+ printf("\n");
+}
+
+/*
+ * Generate data from st with its current internal state and check for
+ * significant bias in each bit of the resulting bytes. This test would have a
+ * small chance of failure on random inputs, but we have a predictable state
+ * after all the other tests have been run, so it will never fail if the PRNG
+ * operates the way we expect.
+ */
+static void
+head_tail_test(struct fortuna_state *st)
+{
+ static unsigned char buffer[1024 * 1024];
+ unsigned char c;
+ size_t i, len = sizeof(buffer);
+ int bit, bits[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ double res;
+
+ memset(buffer, 0, len);
+
+ generator_output(st, buffer, len);
+ for (i = 0; i < len; i++) {
+ c = buffer[i];
+ for (bit = 0; bit < 8 && c; bit++) {
+ if (c & 1)
+ bits[bit]++;
+ c = c >> 1;
+ }
+ }
+
+ for (bit = 0; bit < 8; bit++) {
+ res = ((double)abs(len - bits[bit] * 2)) / (double)len;
+ if (res > 0.005){
+ fprintf(stderr,
+ "Bit %d: %d zero, %d one exceeds 0.5%% variance (%f)\n",
+ bit, (int)len - bits[bit], bits[bit], res);
+ exit(1);
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ struct fortuna_state test_state;
+ struct fortuna_state *st = &test_state;
+ static unsigned char buf[2 * 1024 * 1024];
+ unsigned int i;
+
+ /* Seed the generator with a known state. */
+ init_state(&test_state);
+ generator_reseed(st, (unsigned char *)"test", 4);
+
+ /* Generate two pieces of output; key should change for each request. */
+ generator_output(st, buf, 32);
+ display(buf, 32);
+ generator_output(st, buf, 32);
+ display(buf, 32);
+
+ /* Generate a lot of output to test key changes during request. */
+ generator_output(st, buf, sizeof(buf));
+ display(buf, 32);
+ display(buf + sizeof(buf) - 32, 32);
+
+ /* Reseed the generator and generate more output. */
+ generator_reseed(st, (unsigned char *)"retest", 6);
+ generator_output(st, buf, 32);
+ display(buf, 32);
+
+ /* Add sample data to accumulator pools. */
+ for (i = 0; i < 44; i++) {
+ store_32_be(i, buf);
+ accumulator_add_event(st, buf, 4);
+ }
+ assert(st->pool_index == 12);
+ assert(st->pool0_bytes == 8);
+
+ /* Exercise accumulator reseeds. */
+ accumulator_reseed(st);
+ generator_output(st, buf, 32);
+ display(buf, 32);
+ accumulator_reseed(st);
+ generator_output(st, buf, 32);
+ display(buf, 32);
+ accumulator_reseed(st);
+ generator_output(st, buf, 32);
+ display(buf, 32);
+ for (i = 0; i < 1000; i++)
+ accumulator_reseed(st);
+ assert(st->reseed_count == 1003);
+ generator_output(st, buf, 32);
+ display(buf, 32);
+
+ head_tail_test(st);
+ return 0;
+}
+
+#else /* FORTUNA */
+
+int
+main()
+{
+ return 0;
+}
+
+#endif /* FORTUNA */
diff --git a/src/lib/crypto/krb/t_fortuna.expected b/src/lib/crypto/krb/t_fortuna.expected
new file mode 100644
index 000000000000..2d5738c15f2d
--- /dev/null
+++ b/src/lib/crypto/krb/t_fortuna.expected
@@ -0,0 +1,9 @@
+A7C846B4EEAF6AB78AB33FFC77197BB0364C364E5A4259593464162B14C494F1
+EDC0776CA17E4FC395823653D1956D6873A55A1829D85D8B46340F3C9DD113F2
+B551F4EDF860BEB49E89BFF9B60BFD955ED85B070E18667189450962C503CBE5
+069A4F41D88CC12927672F1039C50DD50A0713E0AD542A6CDCD1E75CC4E7FB36
+E4EBA939FB027DACF1E7406461703C57B48D8BC0A1039A170FAD5E35C088B789
+68199B6755105BC22C343BD339EA2035E7A3F9535DC83DE3436C794EABA18B34
+49AD3C22E015666A269F37CA47EEF075860CC21588F3CF8D7EB5A9DC4D59C0F4
+9EFCB204F1B588A918B6A81D1E0E25C78C0921CF4839BE38D698EE8E30097BED
+66B252E879C2548A3FC3FEAF6B7ABCDBAFB1A45F5FB68EB49AB12CC13B1A091B
diff --git a/src/lib/crypto/krb/valid_cksumtype.c b/src/lib/crypto/krb/valid_cksumtype.c
new file mode 100644
index 000000000000..eb7807f7eda2
--- /dev/null
+++ b/src/lib/crypto/krb/valid_cksumtype.c
@@ -0,0 +1,39 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_boolean KRB5_CALLCONV
+krb5_c_valid_cksumtype(krb5_cksumtype ctype)
+{
+ const struct krb5_cksumtypes *ctp;
+
+ ctp = find_cksumtype(ctype);
+ if (ctp == NULL)
+ return FALSE;
+ return TRUE;
+}
diff --git a/src/lib/crypto/krb/verify_checksum.c b/src/lib/crypto/krb/verify_checksum.c
new file mode 100644
index 000000000000..09425ea7aa90
--- /dev/null
+++ b/src/lib/crypto/krb/verify_checksum.c
@@ -0,0 +1,98 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_k_verify_checksum(krb5_context context, krb5_key key,
+ krb5_keyusage usage, const krb5_data *data,
+ const krb5_checksum *cksum, krb5_boolean *valid)
+{
+ const struct krb5_cksumtypes *ctp;
+ krb5_cksumtype cksumtype;
+ krb5_crypto_iov iov;
+ krb5_error_code ret;
+ krb5_data cksum_data;
+ krb5_checksum computed;
+
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = *data;
+
+ /* A 0 checksum type means use the mandatory checksum. */
+ cksumtype = cksum->checksum_type;
+ if (cksumtype == 0 && key != NULL) {
+ ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype,
+ &cksumtype);
+ if (ret)
+ return ret;
+ }
+ ctp = find_cksumtype(cksumtype);
+ if (ctp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ ret = verify_key(ctp, key);
+ if (ret != 0)
+ return ret;
+
+ /* If there's actually a verify function, call it. */
+ cksum_data = make_data(cksum->contents, cksum->length);
+ if (ctp->verify != NULL)
+ return ctp->verify(ctp, key, usage, &iov, 1, &cksum_data, valid);
+
+ /* Otherwise, make the checksum again, and compare. */
+ if (cksum->length != ctp->output_size)
+ return KRB5_BAD_MSIZE;
+
+ ret = krb5_k_make_checksum(context, cksum->checksum_type, key, usage,
+ data, &computed);
+ if (ret)
+ return ret;
+
+ *valid = (k5_bcmp(computed.contents, cksum->contents,
+ ctp->output_size) == 0);
+
+ free(computed.contents);
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *keyblock,
+ krb5_keyusage usage, const krb5_data *data,
+ const krb5_checksum *cksum, krb5_boolean *valid)
+{
+ krb5_key key = NULL;
+ krb5_error_code ret;
+
+ if (keyblock != NULL) {
+ ret = krb5_k_create_key(context, keyblock, &key);
+ if (ret != 0)
+ return ret;
+ }
+ ret = krb5_k_verify_checksum(context, key, usage, data, cksum, valid);
+ krb5_k_free_key(context, key);
+ return ret;
+}
diff --git a/src/lib/crypto/krb/verify_checksum_iov.c b/src/lib/crypto/krb/verify_checksum_iov.c
new file mode 100644
index 000000000000..fc76c0e269f4
--- /dev/null
+++ b/src/lib/crypto/krb/verify_checksum_iov.c
@@ -0,0 +1,101 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/crypto/krb/verify_checksum_iov.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 "crypto_int.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_k_verify_checksum_iov(krb5_context context,
+ krb5_cksumtype checksum_type,
+ krb5_key key,
+ krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ krb5_boolean *valid)
+{
+ const struct krb5_cksumtypes *ctp;
+ krb5_error_code ret;
+ krb5_data computed;
+ krb5_crypto_iov *checksum;
+
+ if (checksum_type == 0) {
+ ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype,
+ &checksum_type);
+ if (ret != 0)
+ return ret;
+ }
+ ctp = find_cksumtype(checksum_type);
+ if (ctp == NULL)
+ return KRB5_BAD_ENCTYPE;
+
+ ret = verify_key(ctp, key);
+ if (ret != 0)
+ return ret;
+
+ checksum = krb5int_c_locate_iov((krb5_crypto_iov *)data, num_data,
+ KRB5_CRYPTO_TYPE_CHECKSUM);
+ if (checksum == NULL || checksum->data.length != ctp->output_size)
+ return KRB5_BAD_MSIZE;
+
+ /* If there's actually a verify function, call it. */
+ if (ctp->verify != NULL) {
+ return ctp->verify(ctp, key, usage, data, num_data, &checksum->data,
+ valid);
+ }
+
+ ret = alloc_data(&computed, ctp->compute_size);
+ if (ret != 0)
+ return ret;
+
+ ret = ctp->checksum(ctp, key, usage, data, num_data, &computed);
+ if (ret == 0) {
+ *valid = (k5_bcmp(computed.data, checksum->data.data,
+ ctp->output_size) == 0);
+ }
+
+ zapfree(computed.data, ctp->compute_size);
+ return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_verify_checksum_iov(krb5_context context,
+ krb5_cksumtype checksum_type,
+ const krb5_keyblock *keyblock,
+ krb5_keyusage usage,
+ const krb5_crypto_iov *data,
+ size_t num_data,
+ krb5_boolean *valid)
+{
+ krb5_key key;
+ krb5_error_code ret;
+
+ ret = krb5_k_create_key(context, keyblock, &key);
+ if (ret != 0)
+ return ret;
+ ret = krb5_k_verify_checksum_iov(context, checksum_type, key, usage, data,
+ num_data, valid);
+ krb5_k_free_key(context, key);
+ return ret;
+}