diff options
author | Sam Hartman <hartmans@mit.edu> | 2009-01-03 23:19:42 +0000 |
---|---|---|
committer | Sam Hartman <hartmans@mit.edu> | 2009-01-03 23:19:42 +0000 |
commit | 0ba5ccd7bb3ea15e44a87f84ca6feed8890f657d (patch) | |
tree | 2049c9c2cb135fe36b14c0a171711259258d18ec /src/lib/crypto | |
parent | ff0a6514c9f4230938c29922d69cbd4e83691adf (diff) | |
download | krb5-0ba5ccd7bb3ea15e44a87f84ca6feed8890f657d.tar.gz krb5-0ba5ccd7bb3ea15e44a87f84ca6feed8890f657d.tar.xz krb5-0ba5ccd7bb3ea15e44a87f84ca6feed8890f657d.zip |
Merge mskrb-integ onto trunk
The mskrb-integ branch includes support for the following projects:
Projects/Aliases
* Projects/PAC and principal APIs
* Projects/AEAD encryption API
* Projects/GSSAPI DCE
* Projects/RFC 3244
In addition, it includes support for enctype negotiation, and a variety of GSS-API extensions.
In the KDC it includes support for protocol transition, constrained delegation
and a new authorization data interface.
The old authorization data interface is also supported.
This commit merges the mskrb-integ branch on to the trunk.
Additional review and testing is required.
Merge commit 'mskrb-integ' into trunk
ticket: new
status: open
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@21690 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/crypto')
30 files changed, 714 insertions, 135 deletions
diff --git a/src/lib/crypto/Makefile.in b/src/lib/crypto/Makefile.in index b6b647858..3012989ee 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 53dc65076..2d9a8353a 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 e73521aba..b82369f32 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 af4852423..025118ed7 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 75bdd2a09..41053ed17 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, ©str, ©strlen); + 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 f30d1b034..fca48e29a 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 aa2da62f7..46455644a 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 8463fc883..42ac395f3 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 3bafb740b..db0e6765a 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 000000000..f7c2fd391 --- /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 a0ec05c5d..b51319b2e 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 a8def7a93..bc40134ef 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 ef40700e1..8abf5af5f 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 f5ba1c655..174fe233f 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 e025cc3eb..d821cf461 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 6c1e6064c..63c43517e 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 4c370c14d..92022b3c8 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 340fc31d3..de11787d1 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 42785f572..c2ff3341c 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 21d95bcc5..4a232ca63 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 6a96faf8f..8ac91e19d 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 000000000..8c2591588 --- /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 9fe8e69e1..867d9a232 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 c729c1d23..ad532b27d 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 0d862c835..3cf4af605 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 4ac9a4c56..ef81d6a35 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 d3f7dd835..f4b7d5f0b 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 000000000..f52fe000d --- /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 f531ee163..72b5595de 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 5627188df..08c0a5c7b 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); |