diff options
author | Ken Hornstein <kenh@cmf.nrl.navy.mil> | 2002-10-24 06:49:59 +0000 |
---|---|---|
committer | Ken Hornstein <kenh@cmf.nrl.navy.mil> | 2002-10-24 06:49:59 +0000 |
commit | 5ffe972e2c0e6c3748b6b6a33a4f5f68736a6dc7 (patch) | |
tree | bea2ed9545782a2999e54a0da60d51c5741fa7c3 /src/lib/crypto | |
parent | a706a2d0d05ecea7a844db7d291493a5d282ed57 (diff) | |
download | krb5-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/ChangeLog | 5 | ||||
-rw-r--r-- | src/lib/crypto/Makefile.in | 9 | ||||
-rw-r--r-- | src/lib/crypto/combine_keys.c | 325 |
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); +} + |