aboutsummaryrefslogtreecommitdiff
path: root/src/lib/crypto
diff options
context:
space:
mode:
authorKen Hornstein <kenh@cmf.nrl.navy.mil>2002-10-24 06:49:59 +0000
committerKen Hornstein <kenh@cmf.nrl.navy.mil>2002-10-24 06:49:59 +0000
commit5ffe972e2c0e6c3748b6b6a33a4f5f68736a6dc7 (patch)
treebea2ed9545782a2999e54a0da60d51c5741fa7c3 /src/lib/crypto
parenta706a2d0d05ecea7a844db7d291493a5d282ed57 (diff)
downloadkrb5-5ffe972e2c0e6c3748b6b6a33a4f5f68736a6dc7.zip
krb5-5ffe972e2c0e6c3748b6b6a33a4f5f68736a6dc7.tar.gz
krb5-5ffe972e2c0e6c3748b6b6a33a4f5f68736a6dc7.tar.bz2
Client code lacks support for draft-ietf-krb-wg-kerberos-sam-01.txt
This widely-spread commit implements support for the so-called "new" hardware preauth protocol, defined in the IETF internet-draft draft-ietf-krb-wg-kerberos-sam-01.txt. Note that this code is client-side only. ticket: new git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@14939 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/crypto')
-rw-r--r--src/lib/crypto/ChangeLog5
-rw-r--r--src/lib/crypto/Makefile.in9
-rw-r--r--src/lib/crypto/combine_keys.c325
3 files changed, 339 insertions, 0 deletions
diff --git a/src/lib/crypto/ChangeLog b/src/lib/crypto/ChangeLog
index cf91d7b..36b03a5 100644
--- a/src/lib/crypto/ChangeLog
+++ b/src/lib/crypto/ChangeLog
@@ -1,3 +1,8 @@
+2002-10-24 Ken Hornstein <kenh@cmf.nrl.navy.mil>
+
+ * Makefile.in, combine_keys.c: New file to implement
+ key-combination algorithm.
+
2002-10-09 Ken Raeburn <raeburn@mit.edu>
* pbkdf2.c, t_hmac.c, t_pkcs5.c: New files.
diff --git a/src/lib/crypto/Makefile.in b/src/lib/crypto/Makefile.in
index 3273a82..5dc5574 100644
--- a/src/lib/crypto/Makefile.in
+++ b/src/lib/crypto/Makefile.in
@@ -39,6 +39,7 @@ STLIBOBJS=\
cksumtype_to_string.o \
cksumtypes.o \
coll_proof_cksum.o \
+ combine_keys.o \
crypto_libinit.o \
default_state.o \
decrypt.o \
@@ -69,6 +70,7 @@ OBJS=\
$(OUTPRE)cksumtype_to_string.$(OBJEXT) \
$(OUTPRE)cksumtypes.$(OBJEXT) \
$(OUTPRE)coll_proof_cksum.$(OBJEXT) \
+ $(OUTPRE)combine_keys.$(OBJEXT) \
$(OUTPRE)crypto_libinit.$(OBJEXT) \
$(OUTPRE)default_state.$(OBJEXT) \
$(OUTPRE)decrypt.$(OBJEXT) \
@@ -99,6 +101,7 @@ SRCS=\
$(srcdir)/cksumtype_to_string.c \
$(srcdir)/cksumtypes.c \
$(srcdir)/coll_proof_cksum.c \
+ $(srcdir)/combine_keys.c \
$(srcdir)/crypto_libinit.c \
$(srcdir)/default_state.c \
$(srcdir)/decrypt.c \
@@ -348,6 +351,12 @@ coll_proof_cksum.so coll_proof_cksum.po $(OUTPRE)coll_proof_cksum.$(OBJEXT): col
$(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
$(SRCTOP)/include/krb5/kdb.h $(BUILDTOP)/include/profile.h \
cksumtypes.h
+combine_keys.so combine_keys.po $(OUTPRE)combine_keys.$(OBJEXT): combine_keys.c \
+ $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(BUILDTOP)/include/krb5.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/include/krb5/kdb.h $(BUILDTOP)/include/profile.h \
+ etypes.h $(srcdir)/dk/dk.h
crypto_libinit.so crypto_libinit.po $(OUTPRE)crypto_libinit.$(OBJEXT): crypto_libinit.c \
crypto_libinit.h
default_state.so default_state.po $(OUTPRE)default_state.$(OBJEXT): default_state.c $(SRCTOP)/include/k5-int.h \
diff --git a/src/lib/crypto/combine_keys.c b/src/lib/crypto/combine_keys.c
new file mode 100644
index 0000000..472c07e
--- /dev/null
+++ b/src/lib/crypto/combine_keys.c
@@ -0,0 +1,325 @@
+/*
+ * 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 (krb5_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 "k5-int.h"
+#include "etypes.h"
+#include "dk.h"
+
+static krb5_error_code dr
+(const struct krb5_enc_provider *enc, const krb5_keyblock *inkey,
+ unsigned char *outdata, const krb5_data *in_constant);
+
+krb5_error_code KRB5_CALLCONV krb5int_c_combine_keys
+(krb5_context context, krb5_keyblock *key1, krb5_keyblock *key2, krb5_keyblock *outkey)
+{
+ unsigned char *r1, *r2, *combined, *rnd, *output;
+ size_t keybytes, keylength;
+ const struct krb5_enc_provider *enc;
+ krb5_data input, randbits;
+ krb5_keyblock tkey;
+ krb5_error_code ret;
+ int i, myalloc = 0;
+
+ if (key1->length != key2->length || key1->enctype != key2->enctype)
+ return (KRB5_CRYPTO_INTERNAL);
+
+ /*
+ * Find our encryption algorithm
+ */
+
+ for (i = 0; i < krb5_enctypes_length; i++) {
+ if (krb5_enctypes_list[i].etype == key1->enctype)
+ break;
+ }
+
+ if (i == krb5_enctypes_length)
+ return (KRB5_BAD_ENCTYPE);
+
+ enc = krb5_enctypes_list[i].enc;
+
+ (*(enc->keysize))(&keybytes, &keylength);
+
+ /*
+ * Allocate and set up buffers
+ */
+
+ if ((r1 = (unsigned char *) malloc(keybytes)) == NULL)
+ return (ENOMEM);
+
+ if ((r2 = (unsigned char *) malloc(keybytes)) == NULL) {
+ free(r1);
+ return (ENOMEM);
+ }
+
+ if ((rnd = (unsigned char *) malloc(keybytes)) == NULL) {
+ free(r1);
+ free(r2);
+ return (ENOMEM);
+ }
+
+ if ((combined = (unsigned char *) malloc(keybytes * 2)) == NULL) {
+ free(r1);
+ free(r2);
+ free(rnd);
+ return (ENOMEM);
+ }
+
+ if ((output = (unsigned char *) malloc(keylength)) == NULL) {
+ free(r1);
+ free(r2);
+ free(rnd);
+ free(combined);
+ return (ENOMEM);
+ }
+
+ /*
+ * 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;
+ if ((ret = dr(enc, key1, r1, &input)))
+ goto cleanup;
+
+#if 0
+ {
+ int i;
+ printf("R1 =");
+ for (i = 0; i < keybytes; i++)
+ printf(" %02x", (unsigned char) r1[i]);
+ printf("\n");
+ }
+#endif
+
+ input.length = key1->length;
+ input.data = (char *) key1->contents;
+ if ((ret = dr(enc, key2, r2, &input)))
+ goto cleanup;
+
+#if 0
+ {
+ int i;
+ printf("R2 =");
+ for (i = 0; i < keybytes; i++)
+ printf(" %02x", (unsigned char) r2[i]);
+ printf("\n");
+ }
+#endif
+
+ /*
+ * 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 krb5_nfold() takes sizes in bits, hence
+ * the multiply by 8.
+ */
+
+ memcpy(combined, r1, keybytes);
+ memcpy(combined + keybytes, r2, keybytes);
+
+ krb5_nfold((keybytes * 2) * 8, combined, keybytes * 8, rnd);
+
+#if 0
+ {
+ int i;
+ printf("rnd =");
+ for (i = 0; i < keybytes; i++)
+ printf(" %02x", (unsigned char) rnd[i]);
+ printf("\n");
+ }
+#endif
+
+ /*
+ * Run the "random" bits through random-to-key to produce a encryption
+ * key.
+ */
+
+ randbits.length = keybytes;
+ randbits.data = (char *) rnd;
+ tkey.length = keylength;
+ tkey.contents = output;
+
+ if ((ret = (*(enc->make_key))(&randbits, &tkey)))
+ goto cleanup;
+
+#if 0
+ {
+ int i;
+ printf("tkey =");
+ for (i = 0; i < tkey.length; i++)
+ printf(" %02x", (unsigned char) tkey.contents[i]);
+ printf("\n");
+ }
+#endif
+
+ /*
+ * 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; /* Note; change this if string length changes */
+ 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 = (krb5_octet *) malloc(keylength);
+ if (!outkey->contents) {
+ ret = ENOMEM;
+ goto cleanup;
+ }
+ outkey->length = keylength;
+ outkey->enctype = key1->enctype;
+ myalloc = 1;
+ }
+
+ if ((ret = krb5_derive_key(enc, &tkey, outkey, &input))) {
+ if (myalloc) {
+ free(outkey->contents);
+ outkey->contents = NULL;
+ }
+ goto cleanup;
+ }
+
+#if 0
+ {
+ int i;
+ printf("output =");
+ for (i = 0; i < outkey->length; i++)
+ printf(" %02x", (unsigned char) outkey->contents[i]);
+ printf("\n");
+ }
+#endif
+
+ ret = 0;
+
+cleanup:
+ memset(r1, 0, keylength);
+ memset(r2, 0, keylength);
+ memset(rnd, 0, keybytes);
+ memset(combined, 0, keylength * 2);
+ memset(output, 0, keylength);
+
+ free(r1);
+ free(r2);
+ free(rnd);
+ free(combined);
+ free(output);
+
+ return (ret);
+}
+
+/*
+ * Our DR function; mostly taken from derive.c
+ */
+
+static krb5_error_code dr
+(const struct krb5_enc_provider *enc, const krb5_keyblock *inkey, unsigned char *out, const krb5_data *in_constant)
+{
+ size_t blocksize, keybytes, keylength, n;
+ unsigned char *inblockdata, *outblockdata;
+ krb5_data inblock, outblock;
+
+ (*(enc->block_size))(&blocksize);
+ (*(enc->keysize))(&keybytes, &keylength);
+
+ /* allocate and set up buffers */
+
+ if ((inblockdata = (unsigned char *) malloc(blocksize)) == NULL)
+ return(ENOMEM);
+
+ if ((outblockdata = (unsigned char *) malloc(blocksize)) == NULL) {
+ free(inblockdata);
+ return(ENOMEM);
+ }
+
+ inblock.data = (char *) inblockdata;
+ inblock.length = blocksize;
+
+ outblock.data = (char *) outblockdata;
+ outblock.length = blocksize;
+
+ /* initialize the input block */
+
+ if (in_constant->length == inblock.length) {
+ memcpy(inblock.data, in_constant->data, inblock.length);
+ } else {
+ krb5_nfold(in_constant->length*8, (unsigned char *) in_constant->data,
+ inblock.length*8, (unsigned char *) inblock.data);
+ }
+
+ /* loop encrypting the blocks until enough key bytes are generated */
+
+ n = 0;
+ while (n < keybytes) {
+ (*(enc->encrypt))(inkey, 0, &inblock, &outblock);
+
+ if ((keybytes - n) <= outblock.length) {
+ memcpy(out+n, outblock.data, (keybytes - n));
+ break;
+ }
+
+ memcpy(out+n, outblock.data, outblock.length);
+ memcpy(inblock.data, outblock.data, outblock.length);
+ n += outblock.length;
+ }
+
+ /* clean memory, free resources and exit */
+
+ memset(inblockdata, 0, blocksize);
+ memset(outblockdata, 0, blocksize);
+
+ free(outblockdata);
+ free(inblockdata);
+
+ return(0);
+}
+