summaryrefslogtreecommitdiffstats
path: root/src/lib/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/crypto')
-rw-r--r--src/lib/crypto/Makefile.in2
-rw-r--r--src/lib/crypto/aead.c12
-rw-r--r--src/lib/crypto/arcfour/Makefile.in9
-rw-r--r--src/lib/crypto/arcfour/arcfour_aead.c4
-rw-r--r--src/lib/crypto/arcfour/arcfour_s2k.c67
-rw-r--r--src/lib/crypto/cksumtypes.c4
-rw-r--r--src/lib/crypto/des/Makefile.in13
-rw-r--r--src/lib/crypto/des/d3_aead.c13
-rw-r--r--src/lib/crypto/des/des_int.h11
-rw-r--r--src/lib/crypto/des/f_aead.c192
-rw-r--r--src/lib/crypto/dk/checksum.c4
-rw-r--r--src/lib/crypto/dk/dk.h24
-rw-r--r--src/lib/crypto/dk/dk_aead.c11
-rw-r--r--src/lib/crypto/enc_provider/Makefile.in7
-rw-r--r--src/lib/crypto/enc_provider/aes.c31
-rw-r--r--src/lib/crypto/enc_provider/des.c66
-rw-r--r--src/lib/crypto/enc_provider/enc_provider.h2
-rw-r--r--src/lib/crypto/etypes.c4
-rw-r--r--src/lib/crypto/hmac.c5
-rw-r--r--src/lib/crypto/keyhash_provider/Makefile.in18
-rw-r--r--src/lib/crypto/keyhash_provider/keyhash_provider.h3
-rw-r--r--src/lib/crypto/keyhash_provider/md5_hmac.c68
-rw-r--r--src/lib/crypto/libk5crypto.exports1
-rw-r--r--src/lib/crypto/make_checksum.c16
-rw-r--r--src/lib/crypto/make_checksum_iov.c28
-rw-r--r--src/lib/crypto/raw/Makefile.in18
-rw-r--r--src/lib/crypto/raw/raw.h3
-rw-r--r--src/lib/crypto/raw/raw_aead.c163
-rw-r--r--src/lib/crypto/verify_checksum.c20
-rw-r--r--src/lib/crypto/verify_checksum_iov.c30
30 files changed, 714 insertions, 135 deletions
diff --git a/src/lib/crypto/Makefile.in b/src/lib/crypto/Makefile.in
index b6b6478588..3012989ee8 100644
--- a/src/lib/crypto/Makefile.in
+++ b/src/lib/crypto/Makefile.in
@@ -8,7 +8,7 @@ LOCALINCLUDES = -I$(srcdir)/enc_provider \
-I$(srcdir)/hash_provider -I$(srcdir)/keyhash_provider \
-I$(srcdir)/aes \
-I$(srcdir)/old -I$(srcdir)/raw -I$(srcdir)/dk -I$(srcdir)/arcfour \
- -I$(srcdir)/yarrow -I$(srcdir)/sha1
+ -I$(srcdir)/yarrow -I$(srcdir)/sha1 -I$(srcdir)/md5
RUN_SETUP = @KRB5_RUN_ENV@
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
diff --git a/src/lib/crypto/aead.c b/src/lib/crypto/aead.c
index 53dc65076d..2d9a8353af 100644
--- a/src/lib/crypto/aead.c
+++ b/src/lib/crypto/aead.c
@@ -130,9 +130,9 @@ krb5int_c_make_checksum_iov(const struct krb5_cksumtypes *cksum_type,
ret = (*(cksum_type->keyhash->hash_iov))(key, usage, 0,
data, num_data, cksum_data);
} else if (cksum_type->flags & KRB5_CKSUMFLAG_DERIVE) {
- ret = krb5_dk_make_checksum_iov(cksum_type->hash,
- key, usage, data, num_data,
- cksum_data);
+ ret = krb5int_dk_make_checksum_iov(cksum_type->hash,
+ key, usage, data, num_data,
+ cksum_data);
} else {
ret = make_unkeyed_checksum_iov(cksum_type->hash, data, num_data,
cksum_data);
@@ -289,8 +289,7 @@ krb5int_c_iov_get_block(unsigned char *block,
memset(block + j, 0, block_size - j);
#ifdef DEBUG_IOV
- if (iov_state->iov_pos < num_data)
- dump_block("get_block", i, j, block, block_size);
+ dump_block("get_block", i, j, block, block_size);
#endif
return (iov_state->iov_pos < num_data);
@@ -339,8 +338,7 @@ krb5int_c_iov_put_block(const krb5_crypto_iov *data,
iov_state->iov_pos = i;
#ifdef DEBUG_IOV
- if (iov_state->iov_pos < num_data)
- dump_block("put_block", i, j, block, block_size);
+ dump_block("put_block", i, j, block, block_size);
#endif
return (iov_state->iov_pos < num_data);
diff --git a/src/lib/crypto/arcfour/Makefile.in b/src/lib/crypto/arcfour/Makefile.in
index e73521aba3..b82369f320 100644
--- a/src/lib/crypto/arcfour/Makefile.in
+++ b/src/lib/crypto/arcfour/Makefile.in
@@ -74,7 +74,8 @@ arcfour_s2k.so arcfour_s2k.po $(OUTPRE)arcfour_s2k.$(OBJEXT): \
$(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
$(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
$(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
- $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
- $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
- $(SRCTOP)/include/socket-utils.h $(srcdir)/../md4/rsa-md4.h \
- arcfour-int.h arcfour.h arcfour_s2k.c
+ $(SRCTOP)/include/k5-utf8.h $(SRCTOP)/include/krb5.h \
+ $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(srcdir)/../md4/rsa-md4.h arcfour-int.h arcfour.h \
+ arcfour_s2k.c
diff --git a/src/lib/crypto/arcfour/arcfour_aead.c b/src/lib/crypto/arcfour/arcfour_aead.c
index af48524232..025118ed7d 100644
--- a/src/lib/crypto/arcfour/arcfour_aead.c
+++ b/src/lib/crypto/arcfour/arcfour_aead.c
@@ -176,7 +176,7 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead,
header->data.length -= hash->hashsize;
header->data.data += hash->hashsize;
- ret = krb5_hmac_iov(hash, &k2, data, num_data, &checksum);
+ ret = krb5int_hmac_iov(hash, &k2, data, num_data, &checksum);
if (ret != 0)
goto cleanup;
@@ -289,7 +289,7 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead,
if (ret != 0)
goto cleanup;
- ret = krb5_hmac_iov(hash, &k2, data, num_data, &d1);
+ ret = krb5int_hmac_iov(hash, &k2, data, num_data, &d1);
if (ret != 0)
goto cleanup;
diff --git a/src/lib/crypto/arcfour/arcfour_s2k.c b/src/lib/crypto/arcfour/arcfour_s2k.c
index 75bdd2a09d..41053ed17d 100644
--- a/src/lib/crypto/arcfour/arcfour_s2k.c
+++ b/src/lib/crypto/arcfour/arcfour_s2k.c
@@ -1,4 +1,5 @@
#include "k5-int.h"
+#include "k5-utf8.h"
#include "rsa-md4.h"
#include "arcfour-int.h"
@@ -6,58 +7,15 @@
#include <CoreFoundation/CFString.h>
#endif
-static krb5_error_code
-utf8to16(unsigned char *utf16_buf, const char *utf8_str, size_t *len)
-{
- krb5_error_code err = 0;
-
-#if TARGET_OS_MAC && !defined(DEPEND)
- CFStringRef string = NULL;
- CFIndex length = *len;
-
- string = CFStringCreateWithCString (kCFAllocatorDefault,
- utf8_str, kCFStringEncodingUTF8);
- if (!string) { err = ENOMEM; }
-
- if (!err) {
- CFIndex copied = 0;
- CFRange range = CFRangeMake (0, CFStringGetLength (string));
-
- copied = CFStringGetBytes (string, range, kCFStringEncodingUTF16LE,
- 0, false, utf16_buf, length, &length);
- if (copied != range.length) { err = ENOMEM; }
- }
-
- if (!err) {
- *len = length;
- }
-
- if (string) { CFRelease (string); }
-
-#else
- /*
- * This should be re-evaluated in the future, it makes the assumption that
- * the user's password is in ascii, not utf-8. Use iconv?
- */
- size_t counter;
- for (counter=0;counter<*len;counter++) {
- utf16_buf[2*counter]=utf8_str[counter];
- utf16_buf[2*counter + 1]=0x00;
- }
-#endif
-
- return err;
-}
-
krb5_error_code
krb5int_arcfour_string_to_key(const struct krb5_enc_provider *enc,
const krb5_data *string, const krb5_data *salt,
const krb5_data *params, krb5_keyblock *key)
{
krb5_error_code err = 0;
- size_t len;
- unsigned char *copystr;
krb5_MD4_CTX md4_context;
+ unsigned char *copystr;
+ size_t copystrlen;
if (params != NULL)
return KRB5_ERR_BAD_S2K_PARAMS;
@@ -71,22 +29,14 @@ krb5int_arcfour_string_to_key(const struct krb5_enc_provider *enc,
Since the password must be stored in unicode, we need to increase
that number by 2x.
*/
- if (string->length > (SIZE_MAX/2))
- return (KRB5_BAD_MSIZE);
- len= string->length * 2;
-
- copystr = malloc(len);
- if (copystr == NULL)
- return ENOMEM;
-
- /* make the string. start by creating the unicode version of the password*/
- err = utf8to16(copystr, string->data, &len);
- if (err) goto cleanup;
+ err = krb5int_utf8cs_to_ucs2les(string->data, string->length, &copystr, &copystrlen);
+ if (err)
+ return err;
/* the actual MD4 hash of the data */
krb5_MD4Init(&md4_context);
- krb5_MD4Update(&md4_context, (unsigned char *)copystr, len);
+ krb5_MD4Update(&md4_context, copystr, copystrlen);
krb5_MD4Final(&md4_context);
memcpy(key->contents, md4_context.digest, 16);
@@ -101,9 +51,8 @@ krb5int_arcfour_string_to_key(const struct krb5_enc_provider *enc,
}
#endif /* 0 */
-cleanup:
/* Zero out the data behind us */
- memset (copystr, 0, len);
+ memset(copystr, 0, copystrlen);
memset(&md4_context, 0, sizeof(md4_context));
free(copystr);
return err;
diff --git a/src/lib/crypto/cksumtypes.c b/src/lib/crypto/cksumtypes.c
index f30d1b034c..fca48e29a5 100644
--- a/src/lib/crypto/cksumtypes.c
+++ b/src/lib/crypto/cksumtypes.c
@@ -92,6 +92,10 @@ const struct krb5_cksumtypes krb5_cksumtypes_list[] = {
"hmac-sha1-96-aes256", "HMAC-SHA1 AES256 key",
0, NULL,
&krb5int_hash_sha1, 12 },
+ { CKSUMTYPE_MD5_HMAC_ARCFOUR, 0,
+ "md5-hmac-rc4", "Microsoft MD5 HMAC (RC4 key)",
+ ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_md5_hmac,
+ NULL }
};
const unsigned int krb5_cksumtypes_length =
diff --git a/src/lib/crypto/des/Makefile.in b/src/lib/crypto/des/Makefile.in
index aa2da62f7a..46455644ad 100644
--- a/src/lib/crypto/des/Makefile.in
+++ b/src/lib/crypto/des/Makefile.in
@@ -18,6 +18,7 @@ STLIBOBJS=\
d3_cbc.o \
d3_aead.o \
d3_kysched.o \
+ f_aead.o \
f_cbc.o \
f_cksum.o \
f_parity.o \
@@ -31,6 +32,7 @@ OBJS= $(OUTPRE)afsstring2key.$(OBJEXT) \
$(OUTPRE)d3_cbc.$(OBJEXT) \
$(OUTPRE)d3_aead.$(OBJEXT) \
$(OUTPRE)d3_kysched.$(OBJEXT) \
+ $(OUTPRE)f_aead.$(OBJEXT) \
$(OUTPRE)f_cbc.$(OBJEXT) \
$(OUTPRE)f_cksum.$(OBJEXT) \
$(OUTPRE)f_parity.$(OBJEXT) \
@@ -44,6 +46,7 @@ SRCS= $(srcdir)/afsstring2key.c \
$(srcdir)/d3_cbc.c \
$(srcdir)/d3_aead.c \
$(srcdir)/d3_kysched.c \
+ $(srcdir)/f_aead.c \
$(srcdir)/f_cbc.c \
$(srcdir)/f_cksum.c \
$(srcdir)/f_parity.c \
@@ -141,6 +144,16 @@ d3_kysched.so d3_kysched.po $(OUTPRE)d3_kysched.$(OBJEXT): \
$(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
$(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
$(SRCTOP)/include/socket-utils.h d3_kysched.c des_int.h
+f_aead.so f_aead.po $(OUTPRE)f_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \
+ $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \
+ $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
+ $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(srcdir)/../aead.h des_int.h f_aead.c f_tables.h
f_cbc.so f_cbc.po $(OUTPRE)f_cbc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
$(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \
diff --git a/src/lib/crypto/des/d3_aead.c b/src/lib/crypto/des/d3_aead.c
index 8463fc8837..42ac395f31 100644
--- a/src/lib/crypto/des/d3_aead.c
+++ b/src/lib/crypto/des/d3_aead.c
@@ -75,6 +75,9 @@ krb5int_des3_cbc_encrypt_iov(krb5_crypto_iov *data,
if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos))
break;
+ if (input_pos.iov_pos == num_data)
+ break;
+
GET_HALF_BLOCK(temp, ip);
left ^= temp;
GET_HALF_BLOCK(temp, ip);
@@ -159,6 +162,9 @@ krb5int_des3_cbc_decrypt_iov(krb5_crypto_iov *data,
if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos))
break;
+ if (input_pos.iov_pos == num_data)
+ break;
+
ip = iblock;
op = oblock;
@@ -193,6 +199,9 @@ krb5int_des3_cbc_decrypt_iov(krb5_crypto_iov *data,
krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
}
- if (ivec != NULL)
- memcpy(ivec, oblock, MIT_DES_BLOCK_LENGTH);
+ if (ivec != NULL) {
+ op = ivec;
+ PUT_HALF_BLOCK(ocipherl,op);
+ PUT_HALF_BLOCK(ocipherr, op);
+ }
}
diff --git a/src/lib/crypto/des/des_int.h b/src/lib/crypto/des/des_int.h
index 3bafb740ba..db0e6765a0 100644
--- a/src/lib/crypto/des/des_int.h
+++ b/src/lib/crypto/des/des_int.h
@@ -324,6 +324,17 @@ krb5int_des_cbc_decrypt(const mit_des_cblock *in,
((enc ? krb5int_des_cbc_encrypt : krb5int_des_cbc_decrypt) \
(in, out, length, schedule, ivec), 0)
+void
+krb5int_des_cbc_encrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule schedule,
+ mit_des_cblock ivec);
+
+void
+krb5int_des_cbc_decrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule schedule,
+ mit_des_cblock ivec);
/* d3_procky.c */
extern krb5_error_code mit_des3_process_key
diff --git a/src/lib/crypto/des/f_aead.c b/src/lib/crypto/des/f_aead.c
new file mode 100644
index 0000000000..f7c2fd3916
--- /dev/null
+++ b/src/lib/crypto/des/f_aead.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2008 by the Massachusetts Institute of Technology.
+ * Copyright 1995 by Richard P. Basch. All Rights Reserved.
+ * Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Richard P. Basch,
+ * Lehman Brothers and M.I.T. make no representations about the suitability
+ * of this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#include "des_int.h"
+#include "f_tables.h"
+#include "../aead.h"
+
+void
+krb5int_des_cbc_encrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule schedule,
+ mit_des_cblock ivec)
+{
+ unsigned DES_INT32 left, right;
+ const unsigned DES_INT32 *kp;
+ const unsigned char *ip;
+ unsigned char *op;
+ struct iov_block_state input_pos, output_pos;
+ unsigned char iblock[MIT_DES_BLOCK_LENGTH];
+ unsigned char oblock[MIT_DES_BLOCK_LENGTH];
+
+ IOV_BLOCK_STATE_INIT(&input_pos);
+ IOV_BLOCK_STATE_INIT(&output_pos);
+
+ /*
+ * Get key pointer here. This won't need to be reinitialized
+ */
+ kp = (const unsigned DES_INT32 *)schedule;
+
+ /*
+ * Initialize left and right with the contents of the initial
+ * vector.
+ */
+ if (ivec != NULL)
+ ip = ivec;
+ else
+ ip = mit_des_zeroblock;
+ GET_HALF_BLOCK(left, ip);
+ GET_HALF_BLOCK(right, ip);
+
+ /*
+ * Suitably initialized, now work the length down 8 bytes
+ * at a time.
+ */
+ for (;;) {
+ unsigned DES_INT32 temp;
+
+ ip = iblock;
+ op = oblock;
+
+ if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos))
+ break;
+
+ if (input_pos.iov_pos == num_data)
+ break;
+
+ GET_HALF_BLOCK(temp, ip);
+ left ^= temp;
+ GET_HALF_BLOCK(temp, ip);
+ right ^= temp;
+
+ /*
+ * Encrypt what we have
+ */
+ DES_DO_ENCRYPT(left, right, kp);
+
+ /*
+ * Copy the results out
+ */
+ PUT_HALF_BLOCK(left, op);
+ PUT_HALF_BLOCK(right, op);
+
+ krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
+ }
+
+ if (ivec != NULL)
+ memcpy(ivec, oblock, MIT_DES_BLOCK_LENGTH);
+}
+
+void
+krb5int_des_cbc_decrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule schedule,
+ mit_des_cblock ivec)
+{
+ unsigned DES_INT32 left, right;
+ const unsigned DES_INT32 *kp;
+ const unsigned char *ip;
+ unsigned DES_INT32 ocipherl, ocipherr;
+ unsigned DES_INT32 cipherl, cipherr;
+ unsigned char *op;
+ struct iov_block_state input_pos, output_pos;
+ unsigned char iblock[MIT_DES_BLOCK_LENGTH];
+ unsigned char oblock[MIT_DES_BLOCK_LENGTH];
+
+ IOV_BLOCK_STATE_INIT(&input_pos);
+ IOV_BLOCK_STATE_INIT(&output_pos);
+
+ /*
+ * Get key pointer here. This won't need to be reinitialized
+ */
+ kp = (const unsigned DES_INT32 *)schedule;
+
+ /*
+ * Decrypting is harder than encrypting because of
+ * the necessity of remembering a lot more things.
+ * Should think about this a little more...
+ */
+
+ if (num_data == 0)
+ return;
+
+ /*
+ * Prime the old cipher with ivec.
+ */
+ if (ivec != NULL)
+ ip = ivec;
+ else
+ ip = mit_des_zeroblock;
+ GET_HALF_BLOCK(ocipherl, ip);
+ GET_HALF_BLOCK(ocipherr, ip);
+
+ /*
+ * Now do this in earnest until we run out of length.
+ */
+ for (;;) {
+ /*
+ * Read a block from the input into left and
+ * right. Save this cipher block for later.
+ */
+
+ if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos))
+ break;
+
+ if (input_pos.iov_pos == num_data)
+ break;
+
+ ip = iblock;
+ op = oblock;
+
+ GET_HALF_BLOCK(left, ip);
+ GET_HALF_BLOCK(right, ip);
+ cipherl = left;
+ cipherr = right;
+
+ /*
+ * Decrypt this.
+ */
+ DES_DO_DECRYPT(left, right, kp);
+
+ /*
+ * Xor with the old cipher to get plain
+ * text. Output 8 or less bytes of this.
+ */
+ left ^= ocipherl;
+ right ^= ocipherr;
+
+ PUT_HALF_BLOCK(left, op);
+ PUT_HALF_BLOCK(right, op);
+
+ /*
+ * Save current cipher block here
+ */
+ ocipherl = cipherl;
+ ocipherr = cipherr;
+
+ krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
+ }
+
+ if (ivec != NULL)
+ memcpy(ivec, oblock, MIT_DES_BLOCK_LENGTH);
+}
diff --git a/src/lib/crypto/dk/checksum.c b/src/lib/crypto/dk/checksum.c
index a0ec05c5d5..b51319b2ea 100644
--- a/src/lib/crypto/dk/checksum.c
+++ b/src/lib/crypto/dk/checksum.c
@@ -103,7 +103,7 @@ cleanup:
}
krb5_error_code
-krb5_dk_make_checksum_iov(const struct krb5_hash_provider *hash,
+krb5int_dk_make_checksum_iov(const struct krb5_hash_provider *hash,
const krb5_keyblock *key, krb5_keyusage usage,
const krb5_crypto_iov *data, size_t num_data,
krb5_data *output)
@@ -159,7 +159,7 @@ krb5_dk_make_checksum_iov(const struct krb5_hash_provider *hash,
/* hash the data */
- if ((ret = krb5_hmac_iov(hash, &kc, data, num_data, output)) != 0)
+ if ((ret = krb5int_hmac_iov(hash, &kc, data, num_data, output)) != 0)
memset(output->data, 0, output->length);
/* ret is set correctly by the prior call */
diff --git a/src/lib/crypto/dk/dk.h b/src/lib/crypto/dk/dk.h
index a8def7a93d..bc40134eff 100644
--- a/src/lib/crypto/dk/dk.h
+++ b/src/lib/crypto/dk/dk.h
@@ -85,7 +85,7 @@ krb5_error_code krb5_dk_make_checksum
const krb5_data *input, krb5_data *output);
krb5_error_code
-krb5_dk_make_checksum_iov(const struct krb5_hash_provider *hash,
+krb5int_dk_make_checksum_iov(const struct krb5_hash_provider *hash,
const krb5_keyblock *key, krb5_keyusage usage,
const krb5_crypto_iov *data, size_t num_data,
krb5_data *output);
@@ -100,3 +100,25 @@ krb5_derive_random(const struct krb5_enc_provider *enc,
extern const struct krb5_aead_provider krb5int_aead_dk;
extern const struct krb5_aead_provider krb5int_aead_aes;
+/* CCM */
+
+void
+krb5int_ccm_encrypt_length(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ size_t inputlen, size_t *length);
+
+extern const struct krb5_aead_provider krb5int_aead_ccm;
+
+krb5_error_code krb5int_ccm_encrypt
+(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key, krb5_keyusage usage,
+ const krb5_data *ivec, const krb5_data *input,
+ krb5_data *arg_output);
+
+krb5_error_code krb5int_ccm_decrypt
+(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key, krb5_keyusage usage,
+ const krb5_data *ivec, const krb5_data *input,
+ krb5_data *arg_output);
diff --git a/src/lib/crypto/dk/dk_aead.c b/src/lib/crypto/dk/dk_aead.c
index ef40700e15..8abf5af5f4 100644
--- a/src/lib/crypto/dk/dk_aead.c
+++ b/src/lib/crypto/dk/dk_aead.c
@@ -176,7 +176,7 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead,
d2.length = hash->hashsize;
d2.data = (char *)cksum;
- ret = krb5_hmac_iov(hash, &ki, data, num_data, &d2);
+ ret = krb5int_hmac_iov(hash, &ki, data, num_data, &d2);
if (ret != 0)
goto cleanup;
@@ -230,6 +230,11 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead,
unsigned int hmacsize = 0;
unsigned char *cksum = NULL;
+ if (krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_STREAM) != NULL) {
+ return krb5int_c_iov_decrypt_stream(aead, enc, hash, key,
+ usage, ivec, data, num_data);
+ }
+
ke.contents = ki.contents = NULL;
ke.length = ki.length = 0;
@@ -252,7 +257,7 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead,
if (blocksize == 0) {
/* Check for correct input length in CTS mode */
- if (enc->block_size != 0 && cipherlen < enc->block_size)
+ if (enc->block_size != 0 && cipherlen < enc->block_size)
return KRB5_BAD_MSIZE;
} else {
/* Check that the input data is correctly padded */
@@ -321,7 +326,7 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead,
d1.length = hash->hashsize; /* non-truncated length */
d1.data = (char *)cksum;
- ret = krb5_hmac_iov(hash, &ki, data, num_data, &d1);
+ ret = krb5int_hmac_iov(hash, &ki, data, num_data, &d1);
if (ret != 0)
goto cleanup;
diff --git a/src/lib/crypto/enc_provider/Makefile.in b/src/lib/crypto/enc_provider/Makefile.in
index f5ba1c655a..174fe233f6 100644
--- a/src/lib/crypto/enc_provider/Makefile.in
+++ b/src/lib/crypto/enc_provider/Makefile.in
@@ -2,7 +2,7 @@ thisconfigdir=../../..
myfulldir=lib/crypto/enc_provider
mydir=lib/crypto/enc_provider
BUILDTOP=$(REL)..$(S)..$(S)..
-LOCALINCLUDES = -I$(srcdir)/../des -I$(srcdir)/../arcfour -I$(srcdir)/../aes
+LOCALINCLUDES = -I$(srcdir)/../des -I$(srcdir)/../arcfour -I$(srcdir)/../aes -I$(srcdir)/..
DEFS=
##DOS##BUILDTOP = ..\..\..
@@ -14,7 +14,7 @@ PROG_RPATH=$(KRB5_LIBDIR)
RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
-STLIBOBJS= des.o des3.o rc4.o aes.o
+STLIBOBJS= des.o des3.o rc4.o aes.o
OBJS= \
$(OUTPRE)des.$(OBJEXT) \
@@ -54,7 +54,8 @@ des.so des.po $(OUTPRE)des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \
$(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \
$(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
- $(srcdir)/../des/des_int.h des.c enc_provider.h
+ $(srcdir)/../aead.h $(srcdir)/../des/des_int.h des.c \
+ enc_provider.h
des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
$(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \
diff --git a/src/lib/crypto/enc_provider/aes.c b/src/lib/crypto/enc_provider/aes.c
index e025cc3ebc..d821cf4614 100644
--- a/src/lib/crypto/enc_provider/aes.c
+++ b/src/lib/crypto/enc_provider/aes.c
@@ -266,12 +266,13 @@ krb5int_aes_encrypt_iov(const krb5_keyblock *key,
xorblock(tmp, blockN1);
enc(tmp2, tmp, &ctx);
memcpy(blockN1, tmp2, BLOCK_SIZE);
- if (ivec != NULL)
- memcpy(ivec->data, tmp2, BLOCK_SIZE);
- /* Put the last two blocks back into the ivec (reverse order) */
+ /* Put the last two blocks back into the iovec (reverse order) */
krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN1, BLOCK_SIZE, &output_pos);
krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN2, BLOCK_SIZE, &output_pos);
+
+ if (ivec != NULL)
+ memcpy(ivec->data, blockN1, BLOCK_SIZE);
}
return 0;
@@ -285,8 +286,8 @@ krb5int_aes_decrypt_iov(const krb5_keyblock *key,
{
aes_ctx ctx;
char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE];
- int nblocks = 0, blockno;
- size_t input_length, i;
+ int nblocks = 0, blockno, i;
+ size_t input_length;
CHECK_SIZES;
@@ -337,25 +338,25 @@ krb5int_aes_decrypt_iov(const krb5_keyblock *key,
/* Decrypt second last block */
dec(tmp2, blockN2, &ctx);
- /* Set tmp3 to last ciphertext block (already padded) */
- memcpy(tmp3, blockN1, BLOCK_SIZE);
/* Set tmp2 to last (possibly partial) plaintext block, and
save it. */
- xorblock(tmp2, tmp3);
- memcpy(blockN1, tmp2, BLOCK_SIZE);
+ xorblock(tmp2, blockN1);
+ memcpy(blockN2, tmp2, BLOCK_SIZE);
+
/* Maybe keep the trailing part, and copy in the last
ciphertext block. */
- memcpy(tmp2, tmp3, BLOCK_SIZE);
+ input_length %= BLOCK_SIZE;
+ memcpy(tmp2, blockN1, input_length ? input_length : BLOCK_SIZE);
dec(tmp3, tmp2, &ctx);
xorblock(tmp3, tmp);
- /* Copy out ivec first before we clobber blockN2 with plaintext */
+ /* Copy out ivec first before we clobber blockN1 with plaintext */
if (ivec != NULL)
- memcpy(ivec->data, blockN2, BLOCK_SIZE);
- memcpy(blockN2, tmp3, BLOCK_SIZE);
+ memcpy(ivec->data, blockN1, BLOCK_SIZE);
+ memcpy(blockN1, tmp3, BLOCK_SIZE);
- /* Put the last two blocks back into the ivec */
- krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN2, BLOCK_SIZE, &output_pos);
+ /* Put the last two blocks back into the iovec */
krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN1, BLOCK_SIZE, &output_pos);
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN2, BLOCK_SIZE, &output_pos);
}
return 0;
diff --git a/src/lib/crypto/enc_provider/des.c b/src/lib/crypto/enc_provider/des.c
index 6c1e6064c2..63c43517eb 100644
--- a/src/lib/crypto/enc_provider/des.c
+++ b/src/lib/crypto/enc_provider/des.c
@@ -27,6 +27,7 @@
#include "k5-int.h"
#include "des_int.h"
#include "enc_provider.h"
+#include "aead.h"
static krb5_error_code
k5_des_docrypt(const krb5_keyblock *key, const krb5_data *ivec,
@@ -106,6 +107,67 @@ k5_des_make_key(const krb5_data *randombits, krb5_keyblock *key)
return(0);
}
+static krb5_error_code
+k5_des_docrypt_iov(const krb5_keyblock *key, const krb5_data *ivec,
+ krb5_crypto_iov *data, size_t num_data, int enc)
+{
+ mit_des_key_schedule schedule;
+ size_t input_length = 0;
+ int i;
+
+ /* key->enctype was checked by the caller */
+
+ if (key->length != 8)
+ return(KRB5_BAD_KEYSIZE);
+
+ for (i = 0; i < num_data; i++) {
+ const krb5_crypto_iov *iov = &data[i];
+
+ if (ENCRYPT_DATA_IOV(iov))
+ input_length += iov->data.length;
+ }
+
+ if ((input_length % 8) != 0)
+ return(KRB5_BAD_MSIZE);
+ if (ivec && (ivec->length != 8))
+ return(KRB5_BAD_MSIZE);
+
+ switch (mit_des_key_sched(key->contents, schedule)) {
+ case -1:
+ return(KRB5DES_BAD_KEYPAR);
+ case -2:
+ return(KRB5DES_WEAK_KEY);
+ }
+
+ /* this has a return value, but the code always returns zero */
+ if (enc)
+ krb5int_des_cbc_encrypt_iov(data, num_data, schedule, ivec ? ivec->data : NULL);
+ else
+ krb5int_des_cbc_decrypt_iov(data, num_data, schedule, ivec ? ivec->data : NULL);
+
+ memset(schedule, 0, sizeof(schedule));
+
+ return(0);
+}
+
+static krb5_error_code
+k5_des_encrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ return k5_des_docrypt_iov(key, ivec, data, num_data, 1);
+}
+
+static krb5_error_code
+k5_des_decrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ return k5_des_docrypt_iov(key, ivec, data, num_data, 0);
+}
+
const struct krb5_enc_provider krb5int_enc_des = {
8,
7, 8,
@@ -113,5 +175,7 @@ const struct krb5_enc_provider krb5int_enc_des = {
k5_des_decrypt,
k5_des_make_key,
krb5int_des_init_state,
- krb5int_default_free_state
+ krb5int_default_free_state,
+ k5_des_encrypt_iov,
+ k5_des_decrypt_iov
};
diff --git a/src/lib/crypto/enc_provider/enc_provider.h b/src/lib/crypto/enc_provider/enc_provider.h
index 4c370c14dd..92022b3c81 100644
--- a/src/lib/crypto/enc_provider/enc_provider.h
+++ b/src/lib/crypto/enc_provider/enc_provider.h
@@ -31,4 +31,6 @@ extern const struct krb5_enc_provider krb5int_enc_des3;
extern const struct krb5_enc_provider krb5int_enc_arcfour;
extern const struct krb5_enc_provider krb5int_enc_aes128;
extern const struct krb5_enc_provider krb5int_enc_aes256;
+extern const struct krb5_enc_provider krb5int_enc_aes128_ctr;
+extern const struct krb5_enc_provider krb5int_enc_aes256_ctr;
diff --git a/src/lib/crypto/etypes.c b/src/lib/crypto/etypes.c
index 340fc31d33..de11787d14 100644
--- a/src/lib/crypto/etypes.c
+++ b/src/lib/crypto/etypes.c
@@ -86,7 +86,7 @@ const struct krb5_keytypes krb5_enctypes_list[] = {
krb5int_des_string_to_key,
NULL, /*PRF*/
0,
- NULL /*AEAD*/ },
+ &krb5int_aead_raw },
{ ENCTYPE_DES3_CBC_RAW,
"des3-cbc-raw", "Triple DES cbc mode raw",
&krb5int_enc_des3, NULL,
@@ -95,7 +95,7 @@ const struct krb5_keytypes krb5_enctypes_list[] = {
krb5int_dk_string_to_key,
NULL, /*PRF*/
0,
- NULL /*AEAD*/ },
+ &krb5int_aead_raw },
{ ENCTYPE_DES3_CBC_SHA1,
"des3-cbc-sha1", "Triple DES cbc mode with HMAC/sha1",
diff --git a/src/lib/crypto/hmac.c b/src/lib/crypto/hmac.c
index 42785f5729..c2ff3341c2 100644
--- a/src/lib/crypto/hmac.c
+++ b/src/lib/crypto/hmac.c
@@ -128,8 +128,8 @@ cleanup:
}
krb5_error_code
-krb5_hmac_iov(const struct krb5_hash_provider *hash, const krb5_keyblock *key,
- const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
+krb5int_hmac_iov(const struct krb5_hash_provider *hash, const krb5_keyblock *key,
+ const krb5_crypto_iov *data, size_t num_data, krb5_data *output)
{
krb5_data *sign_data;
size_t num_sign_data;
@@ -143,6 +143,7 @@ krb5_hmac_iov(const struct krb5_hash_provider *hash, const krb5_keyblock *key,
if (SIGN_IOV(iov))
num_sign_data++;
}
+
/* XXX cleanup to avoid alloc */
sign_data = (krb5_data *)calloc(num_sign_data, sizeof(krb5_data));
if (sign_data == NULL)
diff --git a/src/lib/crypto/keyhash_provider/Makefile.in b/src/lib/crypto/keyhash_provider/Makefile.in
index 21d95bcc5f..4a232ca63b 100644
--- a/src/lib/crypto/keyhash_provider/Makefile.in
+++ b/src/lib/crypto/keyhash_provider/Makefile.in
@@ -16,11 +16,11 @@ PROG_RPATH=$(KRB5_LIBDIR)
RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
-STLIBOBJS= descbc.o k5_md4des.o k5_md5des.o hmac_md5.o
+STLIBOBJS= descbc.o k5_md4des.o k5_md5des.o hmac_md5.o md5_hmac.o
-OBJS= $(OUTPRE)descbc.$(OBJEXT) $(OUTPRE)k5_md4des.$(OBJEXT) $(OUTPRE)k5_md5des.$(OBJEXT) $(OUTPRE)hmac_md5.$(OBJEXT)
+OBJS= $(OUTPRE)descbc.$(OBJEXT) $(OUTPRE)k5_md4des.$(OBJEXT) $(OUTPRE)k5_md5des.$(OBJEXT) $(OUTPRE)hmac_md5.$(OBJEXT) $(OUTPRE)md5_hmac.$(OBJEXT)
-SRCS= $(srcdir)/descbc.c $(srcdir)/k5_md4des.c $(srcdir)/k5_md5des.c $(srcdir)/hmac_md5.c
+SRCS= $(srcdir)/descbc.c $(srcdir)/k5_md4des.c $(srcdir)/k5_md5des.c $(srcdir)/hmac_md5.c $(srcdir)/md5_hmac.c
##DOS##LIBOBJS = $(OBJS)
@@ -104,3 +104,15 @@ hmac_md5.so hmac_md5.po $(OUTPRE)hmac_md5.$(OBJEXT): \
$(srcdir)/../arcfour/arcfour-int.h $(srcdir)/../arcfour/arcfour.h \
$(srcdir)/../hash_provider/hash_provider.h $(srcdir)/../md5/rsa-md5.h \
hmac_md5.c keyhash_provider.h
+md5_hmac.so md5_hmac.po $(OUTPRE)md5_hmac.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \
+ $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
+ $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+ $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+ $(SRCTOP)/include/socket-utils.h $(srcdir)/../arcfour/arcfour-int.h \
+ $(srcdir)/../arcfour/arcfour.h $(srcdir)/../hash_provider/hash_provider.h \
+ $(srcdir)/../md5/rsa-md5.h keyhash_provider.h md5_hmac.c
diff --git a/src/lib/crypto/keyhash_provider/keyhash_provider.h b/src/lib/crypto/keyhash_provider/keyhash_provider.h
index 6a96faf8ff..8ac91e19db 100644
--- a/src/lib/crypto/keyhash_provider/keyhash_provider.h
+++ b/src/lib/crypto/keyhash_provider/keyhash_provider.h
@@ -30,3 +30,6 @@ extern const struct krb5_keyhash_provider krb5int_keyhash_descbc;
extern const struct krb5_keyhash_provider krb5int_keyhash_md4des;
extern const struct krb5_keyhash_provider krb5int_keyhash_md5des;
extern const struct krb5_keyhash_provider krb5int_keyhash_hmac_md5;
+extern const struct krb5_keyhash_provider krb5int_keyhash_md5_hmac;
+extern const struct krb5_keyhash_provider krb5int_keyhash_aescbc_128;
+extern const struct krb5_keyhash_provider krb5int_keyhash_aescbc_256;
diff --git a/src/lib/crypto/keyhash_provider/md5_hmac.c b/src/lib/crypto/keyhash_provider/md5_hmac.c
new file mode 100644
index 0000000000..8c2591588a
--- /dev/null
+++ b/src/lib/crypto/keyhash_provider/md5_hmac.c
@@ -0,0 +1,68 @@
+/*
+ * lib/crypto/keyhash_provider/md5_hmac.c
+ *
+ * Copyright2001 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Implementation of Microsoft KERB_CHECKSUM_MD5_HMAC
+ */
+
+#include "k5-int.h"
+#include "keyhash_provider.h"
+#include "arcfour-int.h"
+#include "rsa-md5.h"
+#include "hash_provider.h"
+
+static krb5_error_code
+k5_md5_hmac_hash (const krb5_keyblock *key, krb5_keyusage usage,
+ const krb5_data *iv,
+ const krb5_data *input, krb5_data *output)
+{
+ krb5_keyusage ms_usage;
+ krb5_MD5_CTX ctx;
+ unsigned char t[4];
+ krb5_data ds;
+
+ krb5_MD5Init(&ctx);
+
+ ms_usage = krb5int_arcfour_translate_usage (usage);
+ t[0] = (ms_usage >> 0) & 0xff;
+ t[1] = (ms_usage >> 8) & 0xff;
+ t[2] = (ms_usage >> 16) & 0xff;
+ t[3] = (ms_usage >> 24) & 0xff;
+
+ krb5_MD5Update(&ctx, t, sizeof(t));
+ krb5_MD5Update(&ctx, (unsigned char *)input->data, input->length);
+ krb5_MD5Final(&ctx);
+
+ ds.length = 16;
+ ds.data = (char *)ctx.digest;
+
+ return krb5_hmac ( &krb5int_hash_md5, key, 1, &ds, output);
+}
+
+const struct krb5_keyhash_provider krb5int_keyhash_md5_hmac = {
+ 16,
+ k5_md5_hmac_hash,
+ NULL /*checksum again*/
+};
+
diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports
index 9fe8e69e15..867d9a2329 100644
--- a/src/lib/crypto/libk5crypto.exports
+++ b/src/lib/crypto/libk5crypto.exports
@@ -69,7 +69,6 @@ krb5_finish_key
krb5_finish_random_key
krb5_free_cksumtypes
krb5_hmac
-krb5_hmac_iov
krb5_init_random_key
krb5_nfold
krb5_old_decrypt
diff --git a/src/lib/crypto/make_checksum.c b/src/lib/crypto/make_checksum.c
index c729c1d23e..ad532b27dd 100644
--- a/src/lib/crypto/make_checksum.c
+++ b/src/lib/crypto/make_checksum.c
@@ -63,6 +63,9 @@ krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype,
if (krb5_cksumtypes_list[i].keyhash) {
/* check if key is compatible */
+ const struct krb5_keyhash_provider *keyhash;
+
+ keyhash = krb5_cksumtypes_list[i].keyhash;
if (krb5_cksumtypes_list[i].keyed_etype) {
for (e1=0; e1<krb5_enctypes_length; e1++)
@@ -82,7 +85,18 @@ krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype,
}
}
- ret = (*(krb5_cksumtypes_list[i].keyhash->hash))(key, usage, 0, input, &data);
+ if (keyhash->hash == NULL) {
+ krb5_crypto_iov iov[1];
+
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[0].data = *input;
+
+ assert(keyhash->hash_iov != NULL);
+
+ ret = (*keyhash->hash_iov)(key, usage, 0, iov, 1, &data);
+ } else {
+ ret = (*keyhash->hash)(key, usage, 0, input, &data);
+ }
} else if (krb5_cksumtypes_list[i].flags & KRB5_CKSUMFLAG_DERIVE) {
ret = krb5_dk_make_checksum(krb5_cksumtypes_list[i].hash,
key, usage, input, &data);
diff --git a/src/lib/crypto/make_checksum_iov.c b/src/lib/crypto/make_checksum_iov.c
index 0d862c8352..3cf4af6052 100644
--- a/src/lib/crypto/make_checksum_iov.c
+++ b/src/lib/crypto/make_checksum_iov.c
@@ -36,10 +36,11 @@ krb5_c_make_checksum_iov(krb5_context context,
krb5_crypto_iov *data,
size_t num_data)
{
- krb5_error_code ret;
+ unsigned int i;
size_t cksumlen;
+ krb5_error_code ret;
+ krb5_data cksum_data;
krb5_crypto_iov *checksum;
- size_t i;
for (i = 0; i < krb5_cksumtypes_length; i++) {
if (krb5_cksumtypes_list[i].ctype == cksumtype)
@@ -49,20 +50,33 @@ krb5_c_make_checksum_iov(krb5_context context,
if (i == krb5_cksumtypes_length)
return(KRB5_BAD_ENCTYPE);
- if (krb5_cksumtypes_list[i].keyhash)
- cksumlen = krb5_cksumtypes_list[i].keyhash->hashsize;
+ if (krb5_cksumtypes_list[i].keyhash != NULL)
+ cksum_data.length = krb5_cksumtypes_list[i].keyhash->hashsize;
+ else
+ cksum_data.length = krb5_cksumtypes_list[i].hash->hashsize;
+
+ if (krb5_cksumtypes_list[i].trunc_size != 0)
+ cksumlen = krb5_cksumtypes_list[i].trunc_size;
else
- cksumlen = krb5_cksumtypes_list[i].hash->hashsize;
+ cksumlen = cksum_data.length;
checksum = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
if (checksum == NULL || checksum->data.length < cksumlen)
return(KRB5_BAD_MSIZE);
- checksum->data.length = cksumlen;
+ cksum_data.data = malloc(cksum_data.length);
+ if (cksum_data.data == NULL)
+ return(ENOMEM);
ret = krb5int_c_make_checksum_iov(&krb5_cksumtypes_list[i],
key, usage, data, num_data,
- &checksum->data);
+ &cksum_data);
+ if (ret == 0) {
+ memcpy(checksum->data.data, cksum_data.data, cksumlen);
+ checksum->data.length = cksumlen;
+ }
+
+ free(cksum_data.data);
return(ret);
}
diff --git a/src/lib/crypto/raw/Makefile.in b/src/lib/crypto/raw/Makefile.in
index 4ac9a4c56f..ef81d6a35c 100644
--- a/src/lib/crypto/raw/Makefile.in
+++ b/src/lib/crypto/raw/Makefile.in
@@ -2,6 +2,7 @@ thisconfigdir=../../..
myfulldir=lib/crypto/raw
mydir=lib/crypto/raw
BUILDTOP=$(REL)..$(S)..$(S)..
+LOCALINCLUDES = -I$(srcdir)/..
DEFS=
##DOS##BUILDTOP = ..\..\..
@@ -13,11 +14,11 @@ PROG_RPATH=$(KRB5_LIBDIR)
RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf
-STLIBOBJS= raw_decrypt.o raw_encrypt.o
+STLIBOBJS= raw_decrypt.o raw_encrypt.o raw_aead.o
-OBJS= $(OUTPRE)raw_decrypt.$(OBJEXT) $(OUTPRE)raw_encrypt.$(OBJEXT)
+OBJS= $(OUTPRE)raw_decrypt.$(OBJEXT) $(OUTPRE)raw_encrypt.$(OBJEXT) $(OUTPRE)raw_aead.$(OBJEXT)
-SRCS= $(srcdir)/raw_decrypt.c $(srcdir)/raw_encrypt.c
+SRCS= $(srcdir)/raw_decrypt.c $(srcdir)/raw_encrypt.c $(srcdir)/raw_aead.c
##DOS##LIBOBJS = $(OBJS)
@@ -56,3 +57,14 @@ raw_encrypt.so raw_encrypt.po $(OUTPRE)raw_encrypt.$(OBJEXT): \
$(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
$(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
$(SRCTOP)/include/socket-utils.h raw.h raw_encrypt.c
+raw_aead.so raw_aead.po $(OUTPRE)raw_aead.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \
+ $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
+ $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+ $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+ $(SRCTOP)/include/socket-utils.h $(srcdir)/../aead.h \
+ raw.h raw_aead.c
diff --git a/src/lib/crypto/raw/raw.h b/src/lib/crypto/raw/raw.h
index d3f7dd835e..f4b7d5f0b7 100644
--- a/src/lib/crypto/raw/raw.h
+++ b/src/lib/crypto/raw/raw.h
@@ -44,3 +44,6 @@ krb5_error_code krb5_raw_decrypt
const krb5_keyblock *key, krb5_keyusage usage,
const krb5_data *ivec, const krb5_data *input,
krb5_data *arg_output);
+
+extern const struct krb5_aead_provider krb5int_aead_raw;
+
diff --git a/src/lib/crypto/raw/raw_aead.c b/src/lib/crypto/raw/raw_aead.c
new file mode 100644
index 0000000000..f52fe000d1
--- /dev/null
+++ b/src/lib/crypto/raw/raw_aead.c
@@ -0,0 +1,163 @@
+/*
+ * lib/crypto/raw/raw_aead.c
+ *
+ * Copyright 2008 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+
+#include "k5-int.h"
+#include "raw.h"
+#include "aead.h"
+
+/* AEAD */
+
+static krb5_error_code
+krb5int_raw_crypto_length(const struct krb5_aead_provider *aead,
+ const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ krb5_cryptotype type,
+ unsigned int *length)
+{
+ switch (type) {
+ case KRB5_CRYPTO_TYPE_PADDING:
+ *length = enc->block_size;
+ break;
+ default:
+ *length = 0;
+ break;
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+krb5int_raw_encrypt_iov(const struct krb5_aead_provider *aead,
+ const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key,
+ krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ krb5_error_code ret;
+ krb5_crypto_iov *padding;
+ size_t i;
+ unsigned int blocksize = 0;
+ unsigned int plainlen = 0;
+ unsigned int padsize = 0;
+
+ ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, &blocksize);
+ if (ret != 0)
+ return ret;
+
+ 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;
+ }
+
+ assert(enc->encrypt_iov != NULL);
+
+ ret = enc->encrypt_iov(key, ivec, data, num_data); /* will update ivec */
+
+ return ret;
+}
+
+static krb5_error_code
+krb5int_raw_decrypt_iov(const struct krb5_aead_provider *aead,
+ const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key,
+ krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ krb5_error_code ret;
+ size_t i;
+ unsigned int blocksize = 0; /* careful, this is enc block size not confounder len */
+ unsigned int cipherlen = 0;
+
+ if (krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_STREAM) != NULL) {
+ return krb5int_c_iov_decrypt_stream(aead, enc, hash, key,
+ usage, ivec, data, num_data);
+ }
+
+
+ /* E(Confounder | Plaintext | Pad) | Checksum */
+
+ ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, &blocksize);
+ if (ret != 0)
+ return ret;
+
+ 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 (enc->block_size != 0 && cipherlen < enc->block_size)
+ return KRB5_BAD_MSIZE;
+ } else {
+ /* Check that the input data is correctly padded */
+ if ((cipherlen % blocksize) != 0)
+ return KRB5_BAD_MSIZE;
+ }
+
+ /* Validate header and trailer lengths */
+
+ /* derive the keys */
+
+ /* decrypt the plaintext (header | data | padding) */
+ assert(enc->decrypt_iov != NULL);
+
+ ret = enc->decrypt_iov(key, ivec, data, num_data); /* will update ivec */
+
+ return ret;
+}
+
+const struct krb5_aead_provider krb5int_aead_raw = {
+ krb5int_raw_crypto_length,
+ krb5int_raw_encrypt_iov,
+ krb5int_raw_decrypt_iov
+};
diff --git a/src/lib/crypto/verify_checksum.c b/src/lib/crypto/verify_checksum.c
index f531ee1639..72b5595de6 100644
--- a/src/lib/crypto/verify_checksum.c
+++ b/src/lib/crypto/verify_checksum.c
@@ -51,10 +51,22 @@ krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key,
indata.length = cksum->length;
indata.data = (char *) cksum->contents;
- if (krb5_cksumtypes_list[i].keyhash &&
- krb5_cksumtypes_list[i].keyhash->verify)
- return((*(krb5_cksumtypes_list[i].keyhash->verify))(key, usage, 0, data,
- &indata, valid));
+ if (krb5_cksumtypes_list[i].keyhash) {
+ const struct krb5_keyhash_provider *keyhash;
+
+ keyhash = krb5_cksumtypes_list[i].keyhash;
+
+ if (keyhash->verify == NULL && keyhash->verify_iov != NULL) {
+ krb5_crypto_iov iov[1];
+
+ iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
+ iov[0].data = *data;
+
+ return (*keyhash->verify_iov)(key, usage, 0, iov, 1, &indata, valid);
+ } else if (keyhash->verify != NULL) {
+ return (*keyhash->verify)(key, usage, 0, data, &indata, valid);
+ }
+ }
/* otherwise, make the checksum again, and compare */
diff --git a/src/lib/crypto/verify_checksum_iov.c b/src/lib/crypto/verify_checksum_iov.c
index 5627188dfb..08c0a5c7bd 100644
--- a/src/lib/crypto/verify_checksum_iov.c
+++ b/src/lib/crypto/verify_checksum_iov.c
@@ -38,12 +38,12 @@ krb5_c_verify_checksum_iov(krb5_context context,
krb5_boolean *valid)
{
unsigned int i;
- size_t hashsize;
+ size_t cksumlen;
krb5_error_code ret;
krb5_data computed;
krb5_crypto_iov *checksum;
- for (i=0; i<krb5_cksumtypes_length; i++) {
+ for (i = 0; i < krb5_cksumtypes_length; i++) {
if (krb5_cksumtypes_list[i].ctype == checksum_type)
break;
}
@@ -60,31 +60,37 @@ krb5_c_verify_checksum_iov(krb5_context context,
if (krb5_cksumtypes_list[i].keyhash &&
krb5_cksumtypes_list[i].keyhash->verify_iov)
return((*(krb5_cksumtypes_list[i].keyhash->verify_iov))(key, usage, 0,
- &checksum->data,
data, num_data,
+ &checksum->data,
valid));
/* otherwise, make the checksum again, and compare */
- if ((ret = krb5_c_checksum_length(context, checksum_type, &hashsize)))
- return(ret);
+ if (krb5_cksumtypes_list[i].keyhash != NULL)
+ computed.length = krb5_cksumtypes_list[i].keyhash->hashsize;
+ else
+ computed.length = krb5_cksumtypes_list[i].hash->hashsize;
- if (checksum->data.length != hashsize)
+ if (krb5_cksumtypes_list[i].trunc_size != 0)
+ cksumlen = krb5_cksumtypes_list[i].trunc_size;
+ else
+ cksumlen = computed.length;
+
+ if (checksum->data.length != cksumlen)
return(KRB5_BAD_MSIZE);
- computed.data = malloc(hashsize);
- if (computed.data == NULL) {
+ computed.data = malloc(computed.length);
+ if (computed.data == NULL)
return(ENOMEM);
- }
- computed.length = hashsize;
if ((ret = krb5int_c_make_checksum_iov(&krb5_cksumtypes_list[i], key, usage,
- data, num_data, &computed))) {
+ data, num_data, &computed))) {
free(computed.data);
return(ret);
}
- *valid = (memcmp(computed.data, &checksum->data, hashsize) == 0);
+ *valid = (computed.length == cksumlen) &&
+ (memcmp(computed.data, checksum->data.data, cksumlen) == 0);
free(computed.data);