From 5ffa313d9f6b7c509aa0d7579273150d71ea0f95 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Fri, 4 Dec 2009 05:12:35 +0000 Subject: Consolidate the IOV and non-IOV encryption/decryption code paths, and drop the _iov suffix from most encryption- and decryption-related functions. The enc_provider encrypt and decrypt functions take IOVs, as do the enctype entries in etypes.c, and there are no separate encrypt_iov or decrypt_iov functions. aead_provider is gone. Enctype functions now take pointers to the enctype entry instead of pointers to the enc/hash/aead providers; this allows dk_encrypt and dk_decrypt to be polymorphic in the length function they use now that AES and DES3 can't differentiate by aead provider. aes_string_to_key needed to be moved into the krb/ fold for this since it's an enctype function; it was duplicated between builtin/ and openssl/ before. This leaves openssl/aes empty; the build system currently demands that all modules have the same directory structure, so the directory and Makefile will stick around for now. Three separate copies of the derive_random logic are also now consolidated into one. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23444 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/crypto/krb/dk/Makefile.in | 6 - src/lib/crypto/krb/dk/deps | 39 ++--- src/lib/crypto/krb/dk/derive.c | 165 ++++++------------- src/lib/crypto/krb/dk/dk.h | 63 +++----- src/lib/crypto/krb/dk/dk_aead.c | 142 +++++------------ src/lib/crypto/krb/dk/dk_decrypt.c | 179 --------------------- src/lib/crypto/krb/dk/dk_encrypt.c | 308 ------------------------------------ src/lib/crypto/krb/dk/stringtokey.c | 65 +++++++- 8 files changed, 182 insertions(+), 785 deletions(-) delete mode 100644 src/lib/crypto/krb/dk/dk_decrypt.c delete mode 100644 src/lib/crypto/krb/dk/dk_encrypt.c (limited to 'src/lib/crypto/krb/dk') diff --git a/src/lib/crypto/krb/dk/Makefile.in b/src/lib/crypto/krb/dk/Makefile.in index c87af05..8d65857 100644 --- a/src/lib/crypto/krb/dk/Makefile.in +++ b/src/lib/crypto/krb/dk/Makefile.in @@ -13,24 +13,18 @@ PROG_RPATH=$(KRB5_LIBDIR) STLIBOBJS=\ checksum.o \ dk_aead.o \ - dk_decrypt.o \ - dk_encrypt.o \ derive.o \ stringtokey.o OBJS=\ $(OUTPRE)checksum.$(OBJEXT) \ $(OUTPRE)dk_aead.$(OBJEXT) \ - $(OUTPRE)dk_decrypt.$(OBJEXT) \ - $(OUTPRE)dk_encrypt.$(OBJEXT) \ $(OUTPRE)derive.$(OBJEXT) \ $(OUTPRE)stringtokey.$(OBJEXT) SRCS=\ $(srcdir)/checksum.c \ $(srcdir)/dk_aead.c \ - $(srcdir)/dk_decrypt.c \ - $(srcdir)/dk_encrypt.c \ $(srcdir)/derive.c \ $(srcdir)/stringtokey.c diff --git a/src/lib/crypto/krb/dk/deps b/src/lib/crypto/krb/dk/deps index 0de06af..1fa446a 100644 --- a/src/lib/crypto/krb/dk/deps +++ b/src/lib/crypto/krb/dk/deps @@ -16,7 +16,7 @@ checksum.so checksum.po $(OUTPRE)checksum.$(OBJEXT): \ dk_aead.so dk_aead.po $(OUTPRE)dk_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../aead.h \ - $(srcdir)/../cksumtypes.h $(top_srcdir)/include/k5-buf.h \ + $(srcdir)/../cksumtypes.h $(srcdir)/../etypes.h $(top_srcdir)/include/k5-buf.h \ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ @@ -24,46 +24,25 @@ dk_aead.so dk_aead.po $(OUTPRE)dk_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \ $(top_srcdir)/include/socket-utils.h dk.h dk_aead.c -dk_decrypt.so dk_decrypt.po $(OUTPRE)dk_decrypt.$(OBJEXT): \ - $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ - $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ - $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ +derive.so derive.po $(OUTPRE)derive.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../etypes.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ - dk.h dk_decrypt.c -dk_encrypt.so dk_encrypt.po $(OUTPRE)dk_encrypt.$(OBJEXT): \ + derive.c dk.h +stringtokey.so stringtokey.po $(OUTPRE)stringtokey.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ - $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ - $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ - $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ - $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ - $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ - $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \ - $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ - dk.h dk_encrypt.c -derive.so derive.po $(OUTPRE)derive.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ - $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ - $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(COM_ERR_DEPS) $(srcdir)/../etypes.h $(top_srcdir)/include/k5-buf.h \ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \ - $(top_srcdir)/include/socket-utils.h derive.c dk.h -stringtokey.so stringtokey.po $(OUTPRE)stringtokey.$(OBJEXT): \ - $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ - $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ - $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ - $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ - $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ - $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ - $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ - $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \ - $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ - dk.h stringtokey.c + $(top_srcdir)/include/socket-utils.h dk.h stringtokey.c diff --git a/src/lib/crypto/krb/dk/derive.c b/src/lib/crypto/krb/dk/derive.c index c963c39..384a5e4 100644 --- a/src/lib/crypto/krb/dk/derive.c +++ b/src/lib/crypto/krb/dk/derive.c @@ -79,86 +79,86 @@ cleanup: return ENOMEM; } -/* - * Compute a derived key into the keyblock outkey. This variation on - * krb5int_derive_key does not cache the result, as it is only used - * directly in situations which are not expected to be repeated with - * the same inkey and constant. - */ krb5_error_code -krb5int_derive_keyblock(const struct krb5_enc_provider *enc, - krb5_key inkey, krb5_keyblock *outkey, - const krb5_data *in_constant) +krb5int_derive_random(const struct krb5_enc_provider *enc, + krb5_key inkey, krb5_data *outrnd, + const krb5_data *in_constant) { size_t blocksize, keybytes, n; - unsigned char *inblockdata = NULL, *outblockdata = NULL, *rawkey = NULL; - krb5_data inblock, outblock; + krb5_crypto_iov iov; krb5_error_code ret; blocksize = enc->block_size; keybytes = enc->keybytes; - if (inkey->keyblock.length != enc->keylength || - outkey->length != enc->keylength) + if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes) return KRB5_CRYPTO_INTERNAL; - /* Allocate and set up buffers. */ - inblockdata = k5alloc(blocksize, &ret); - if (ret) - goto cleanup; - outblockdata = k5alloc(blocksize, &ret); - if (ret) - goto cleanup; - rawkey = k5alloc(keybytes, &ret); + /* Allocate encryption data buffer. */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + ret = alloc_data(&iov.data, blocksize); if (ret) - goto cleanup; - - inblock.data = (char *) inblockdata; - inblock.length = blocksize; - - outblock.data = (char *) outblockdata; - outblock.length = blocksize; + return ret; /* Initialize the input block. */ - - if (in_constant->length == inblock.length) { - memcpy(inblock.data, in_constant->data, inblock.length); + if (in_constant->length == blocksize) { + memcpy(iov.data.data, in_constant->data, blocksize); } else { - krb5int_nfold(in_constant->length*8, (unsigned char *) in_constant->data, - inblock.length*8, (unsigned char *) inblock.data); + krb5int_nfold(in_constant->length * 8, + (unsigned char *) in_constant->data, + blocksize * 8, (unsigned char *) iov.data.data); } - /* Loop encrypting the blocks until enough key bytes are generated */ - + /* Loop encrypting the blocks until enough key bytes are generated. */ n = 0; while (n < keybytes) { - ret = (*enc->encrypt)(inkey, 0, &inblock, &outblock); + ret = enc->encrypt(inkey, 0, &iov, 1); if (ret) goto cleanup; - if ((keybytes - n) <= outblock.length) { - memcpy(rawkey + n, outblock.data, (keybytes - n)); + if ((keybytes - n) <= blocksize) { + memcpy(outrnd->data + n, iov.data.data, (keybytes - n)); break; } - memcpy(rawkey+n, outblock.data, outblock.length); - memcpy(inblock.data, outblock.data, outblock.length); - n += outblock.length; + memcpy(outrnd->data + n, iov.data.data, blocksize); + n += blocksize; } - /* postprocess the key */ +cleanup: + zapfree(iov.data.data, blocksize); + return ret; +} + +/* + * Compute a derived key into the keyblock outkey. This variation on + * krb5int_derive_key does not cache the result, as it is only used + * directly in situations which are not expected to be repeated with + * the same inkey and constant. + */ +krb5_error_code +krb5int_derive_keyblock(const struct krb5_enc_provider *enc, + krb5_key inkey, krb5_keyblock *outkey, + const krb5_data *in_constant) +{ + krb5_error_code ret; + krb5_data rawkey = empty_data(); - inblock.data = (char *) rawkey; - inblock.length = keybytes; + /* Allocate a buffer for the raw key bytes. */ + ret = alloc_data(&rawkey, enc->keybytes); + if (ret) + goto cleanup; - ret = (*enc->make_key)(&inblock, outkey); + /* Derive pseudo-random data for the key bytes. */ + ret = krb5int_derive_random(enc, inkey, &rawkey, in_constant); if (ret) goto cleanup; + /* Postprocess the key. */ + ret = enc->make_key(&rawkey, outkey); + cleanup: - zapfree(inblockdata, blocksize); - zapfree(outblockdata, blocksize); - zapfree(rawkey, keybytes); + zapfree(rawkey.data, enc->keybytes); return ret; } @@ -200,72 +200,3 @@ cleanup: zapfree(keyblock.contents, keyblock.length); return ret; } - -krb5_error_code -krb5int_derive_random(const struct krb5_enc_provider *enc, - krb5_key inkey, krb5_data *outrnd, - const krb5_data *in_constant) -{ - size_t blocksize, keybytes, n; - unsigned char *inblockdata = NULL, *outblockdata = NULL, *rawkey = NULL; - krb5_data inblock, outblock; - krb5_error_code ret; - - blocksize = enc->block_size; - keybytes = enc->keybytes; - - if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes) - return KRB5_CRYPTO_INTERNAL; - - /* Allocate and set up buffers. */ - - inblockdata = k5alloc(blocksize, &ret); - if (ret) - goto cleanup; - outblockdata = k5alloc(blocksize, &ret); - if (ret) - goto cleanup; - rawkey = k5alloc(keybytes, &ret); - if (ret) - goto cleanup; - - 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 { - krb5int_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) { - ret = (*enc->encrypt)(inkey, 0, &inblock, &outblock); - if (ret) - goto cleanup; - - if ((keybytes - n) <= outblock.length) { - memcpy(rawkey + n, outblock.data, (keybytes - n)); - break; - } - - memcpy(rawkey+n, outblock.data, outblock.length); - memcpy(inblock.data, outblock.data, outblock.length); - n += outblock.length; - } - - /* Postprocess the key. */ - memcpy(outrnd->data, rawkey, keybytes); - -cleanup: - zapfree(inblockdata, blocksize); - zapfree(outblockdata, blocksize); - zapfree(rawkey, keybytes); - return ret; -} diff --git a/src/lib/crypto/krb/dk/dk.h b/src/lib/crypto/krb/dk/dk.h index 1ac3fbe..892f6b4 100644 --- a/src/lib/crypto/krb/dk/dk.h +++ b/src/lib/crypto/krb/dk/dk.h @@ -26,55 +26,35 @@ */ #include "k5-int.h" +#include "etypes.h" -void -krb5int_dk_encrypt_length(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - size_t input, size_t *length); +unsigned int +krb5int_dk_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); -krb5_error_code -krb5int_dk_encrypt(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, krb5_keyusage usage, - const krb5_data *ivec, - const krb5_data *input, krb5_data *output); - -void -krb5int_aes_encrypt_length(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - size_t input, size_t *length); +unsigned int +krb5int_aes_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); krb5_error_code -krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, - krb5_keyusage usage, - const krb5_data *ivec, - const krb5_data *input, - krb5_data *output); +krb5int_dk_encrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); krb5_error_code -krb5int_dk_decrypt(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, krb5_keyusage usage, - const krb5_data *ivec, const krb5_data *input, - krb5_data *arg_output); +krb5int_dk_decrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); krb5_error_code -krb5int_aes_dk_decrypt(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, - krb5_keyusage usage, - const krb5_data *ivec, - const krb5_data *input, - krb5_data *arg_output); +krb5int_dk_string_to_key(const struct krb5_keytypes *enc, + const krb5_data *string, const krb5_data *salt, + const krb5_data *params, krb5_keyblock *key); krb5_error_code -krb5int_dk_string_to_key(const struct krb5_enc_provider *enc, - const krb5_data *string, - const krb5_data *salt, - const krb5_data *params, - krb5_keyblock *key); +krb5int_aes_string_to_key(const struct krb5_keytypes *enc, + const krb5_data *string, const krb5_data *salt, + const krb5_data *params, krb5_keyblock *key); krb5_error_code krb5int_derive_keyblock(const struct krb5_enc_provider *enc, @@ -105,8 +85,3 @@ krb5_error_code krb5int_derive_random(const struct krb5_enc_provider *enc, krb5_key inkey, krb5_data *outrnd, const krb5_data *in_constant); - -/* AEAD */ - -extern const struct krb5_aead_provider krb5int_aead_dk; -extern const struct krb5_aead_provider krb5int_aead_aes; diff --git a/src/lib/crypto/krb/dk/dk_aead.c b/src/lib/crypto/krb/dk/dk_aead.c index 1801a73..59c84db 100644 --- a/src/lib/crypto/krb/dk/dk_aead.c +++ b/src/lib/crypto/krb/dk/dk_aead.c @@ -34,63 +34,60 @@ /* AEAD */ -static krb5_error_code -krb5int_dk_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) +unsigned int +krb5int_dk_crypto_length(const struct krb5_keytypes *ktp, krb5_cryptotype type) { switch (type) { case KRB5_CRYPTO_TYPE_HEADER: case KRB5_CRYPTO_TYPE_PADDING: - *length = enc->block_size; - break; + return ktp->enc->block_size; case KRB5_CRYPTO_TYPE_TRAILER: case KRB5_CRYPTO_TYPE_CHECKSUM: - *length = hash->hashsize; - break; + return ktp->hash->hashsize; default: assert(0 && "invalid cryptotype passed to krb5int_dk_crypto_length"); - break; + return 0; } +} - return 0; +unsigned int +krb5int_aes_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + return ktp->enc->block_size; + case KRB5_CRYPTO_TYPE_PADDING: + return 0; + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + return 96 / 8; + default: + assert(0 && "invalid cryptotype passed to krb5int_aes_crypto_length"); + return 0; + } } -static krb5_error_code -krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead, - const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, - krb5_keyusage usage, - const krb5_data *ivec, - krb5_crypto_iov *data, - size_t num_data) +krb5_error_code +krb5int_dk_encrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) { + const struct krb5_enc_provider *enc = ktp->enc; + const struct krb5_hash_provider *hash = ktp->hash; krb5_error_code ret; unsigned char constantdata[K5CLENGTH]; krb5_data d1, d2; krb5_crypto_iov *header, *trailer, *padding; krb5_key ke = NULL, ki = NULL; size_t i; - unsigned int blocksize = 0; - unsigned int plainlen = 0; - unsigned int hmacsize = 0; - unsigned int padsize = 0; + unsigned int blocksize, hmacsize, plainlen = 0, padsize = 0; unsigned char *cksum = NULL; /* E(Confounder | Plaintext | Pad) | Checksum */ - ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, - &blocksize); - if (ret != 0) - return ret; - - ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER, - &hmacsize); - if (ret != 0) - return ret; + blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING); + hmacsize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); for (i = 0; i < num_data; i++) { krb5_crypto_iov *iov = &data[i]; @@ -164,9 +161,7 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead, goto cleanup; /* Encrypt the plaintext (header | data | padding) */ - assert(enc->encrypt_iov != NULL); - - ret = (*enc->encrypt_iov)(ke, ivec, data, num_data); /* updates ivec */ + ret = enc->encrypt(ke, ivec, data, num_data); if (ret != 0) goto cleanup; @@ -183,38 +178,27 @@ cleanup: return ret; } -static krb5_error_code -krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead, - const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, - krb5_keyusage usage, - const krb5_data *ivec, - krb5_crypto_iov *data, - size_t num_data) +krb5_error_code +krb5int_dk_decrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) { + const struct krb5_enc_provider *enc = ktp->enc; + const struct krb5_hash_provider *hash = ktp->hash; krb5_error_code ret; unsigned char constantdata[K5CLENGTH]; krb5_data d1; krb5_crypto_iov *header, *trailer; krb5_key ke = NULL, ki = NULL; size_t i; - unsigned int blocksize = 0; /* enc block size, not confounder len */ - unsigned int cipherlen = 0; - unsigned int hmacsize = 0; + unsigned int blocksize; /* enc block size, not confounder len */ + unsigned int hmacsize, cipherlen = 0; unsigned char *cksum = NULL; /* E(Confounder | Plaintext | Pad) | Checksum */ - ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, - &blocksize); - if (ret != 0) - return ret; - - ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER, - &hmacsize); - if (ret != 0) - return ret; + blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING); + hmacsize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); if (blocksize != 0) { /* Check that the input data is correctly padded. */ @@ -262,9 +246,7 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead, goto cleanup; /* Decrypt the plaintext (header | data | padding). */ - assert(enc->decrypt_iov != NULL); - - ret = (*enc->decrypt_iov)(ke, ivec, data, num_data); /* updates ivec */ + ret = enc->decrypt(ke, ivec, data, num_data); if (ret != 0) goto cleanup; @@ -288,41 +270,3 @@ cleanup: free(cksum); return ret; } - -const struct krb5_aead_provider krb5int_aead_dk = { - krb5int_dk_crypto_length, - krb5int_dk_encrypt_iov, - krb5int_dk_decrypt_iov -}; - -static krb5_error_code -krb5int_aes_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_HEADER: - *length = enc->block_size; - break; - case KRB5_CRYPTO_TYPE_PADDING: - *length = 0; - break; - case KRB5_CRYPTO_TYPE_TRAILER: - case KRB5_CRYPTO_TYPE_CHECKSUM: - *length = 96 / 8; - break; - default: - assert(0 && "invalid cryptotype passed to krb5int_aes_crypto_length"); - break; - } - - return 0; -} - -const struct krb5_aead_provider krb5int_aead_aes = { - krb5int_aes_crypto_length, - krb5int_dk_encrypt_iov, - krb5int_dk_decrypt_iov -}; diff --git a/src/lib/crypto/krb/dk/dk_decrypt.c b/src/lib/crypto/krb/dk/dk_decrypt.c deleted file mode 100644 index 4ef7e47..0000000 --- a/src/lib/crypto/krb/dk/dk_decrypt.c +++ /dev/null @@ -1,179 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (C) 1998 by the FundsXpress, INC. - * - * All rights reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of FundsXpress. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. FundsXpress makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include "k5-int.h" -#include "dk.h" - -#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ - -static krb5_error_code -krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, - krb5_keyusage usage, - const krb5_data *ivec, - const krb5_data *input, - krb5_data *output, - size_t hmacsize, - int ivec_mode); - -krb5_error_code -krb5int_dk_decrypt(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, krb5_keyusage usage, - const krb5_data *ivec, const krb5_data *input, - krb5_data *output) -{ - return krb5_dk_decrypt_maybe_trunc_hmac(enc, hash, key, usage, - ivec, input, output, 0, 0); -} - -krb5_error_code -krb5int_aes_dk_decrypt(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, krb5_keyusage usage, - const krb5_data *ivec, const krb5_data *input, - krb5_data *output) -{ - return krb5_dk_decrypt_maybe_trunc_hmac(enc, hash, key, usage, - ivec, input, output, 96 / 8, 1); -} - -static krb5_error_code -krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, krb5_keyusage usage, - const krb5_data *ivec, const krb5_data *input, - krb5_data *output, size_t hmacsize, - int ivec_mode) -{ - krb5_error_code ret; - size_t hashsize, blocksize, enclen, plainlen; - unsigned char *plaindata = NULL, *cksum = NULL, *cn; - krb5_key ke = NULL, ki = NULL; - krb5_data d1, d2; - unsigned char constantdata[K5CLENGTH]; - - hashsize = hash->hashsize; - blocksize = enc->block_size; - - if (hmacsize == 0) - hmacsize = hashsize; - else if (hmacsize > hashsize) - return KRB5KRB_AP_ERR_BAD_INTEGRITY; - - enclen = input->length - hmacsize; - - /* Allocate and set up ciphertext and to-be-derived keys. */ - plaindata = k5alloc(enclen, &ret); - if (ret != 0) - goto cleanup; - cksum = k5alloc(hashsize, &ret); - if (ret != 0) - goto cleanup; - - /* Derive the keys. */ - - d1.data = (char *) constantdata; - d1.length = K5CLENGTH; - - store_32_be(usage, constantdata); - - d1.data[4] = (char) 0xAA; - - ret = krb5int_derive_key(enc, key, &ke, &d1); - if (ret != 0) - goto cleanup; - - d1.data[4] = 0x55; - - ret = krb5int_derive_key(enc, key, &ki, &d1); - if (ret != 0) - goto cleanup; - - /* decrypt the ciphertext */ - - d1.length = enclen; - d1.data = input->data; - - d2.length = enclen; - d2.data = (char *) plaindata; - - ret = (*enc->decrypt)(ke, ivec, &d1, &d2); - if (ret != 0) - goto cleanup; - - if (ivec != NULL && ivec->length == blocksize) { - if (ivec_mode == 0) - cn = (unsigned char *) d1.data + d1.length - blocksize; - else if (ivec_mode == 1) { - int nblocks = (d1.length + blocksize - 1) / blocksize; - cn = (unsigned char *) d1.data + blocksize * (nblocks - 2); - } else - abort(); - } else - cn = NULL; - - /* Verify the hash. */ - - d1.length = hashsize; - d1.data = (char *) cksum; - - ret = krb5int_hmac(hash, ki, 1, &d2, &d1); - if (ret != 0) - goto cleanup; - - if (memcmp(cksum, input->data+enclen, hmacsize) != 0) { - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; - goto cleanup; - } - - /* - * Because this encoding isn't self-describing wrt length, the - * best we can do here is to compute the length minus the - * confounder. - */ - - plainlen = enclen - blocksize; - - if (output->length < plainlen) - return KRB5_BAD_MSIZE; - - output->length = plainlen; - - memcpy(output->data, d2.data+blocksize, output->length); - - if (cn != NULL) - memcpy(ivec->data, cn, blocksize); - -cleanup: - krb5_k_free_key(NULL, ke); - krb5_k_free_key(NULL, ki); - zapfree(plaindata, enclen); - zapfree(cksum, hashsize); - return ret; -} diff --git a/src/lib/crypto/krb/dk/dk_encrypt.c b/src/lib/crypto/krb/dk/dk_encrypt.c deleted file mode 100644 index 29699d7..0000000 --- a/src/lib/crypto/krb/dk/dk_encrypt.c +++ /dev/null @@ -1,308 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (C) 1998 by the FundsXpress, INC. - * - * All rights reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of FundsXpress. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. FundsXpress makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include "k5-int.h" -#include "dk.h" - -#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ - -/* - * The spec says that the confounder size and padding are specific to - * the encryption algorithm. This code (dk_encrypt_length and - * dk_encrypt) assume the confounder is always the blocksize, and the - * padding is always zero bytes up to the blocksize. If these - * assumptions ever fails, the keytype table should be extended to - * include these bits of info. - */ - -void -krb5int_dk_encrypt_length(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - size_t inputlen, size_t *length) -{ - size_t blocksize, hashsize; - - blocksize = enc->block_size; - hashsize = hash->hashsize; - *length = krb5_roundup(blocksize + inputlen, blocksize) + hashsize; -} - -krb5_error_code -krb5int_dk_encrypt(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, krb5_keyusage usage, - const krb5_data *ivec, const krb5_data *input, - krb5_data *output) -{ - size_t blocksize, plainlen, enclen; - krb5_error_code ret; - unsigned char constantdata[K5CLENGTH]; - krb5_data d1, d2; - unsigned char *plaintext = NULL; - char *cn; - krb5_key ke = NULL, ki = NULL; - - blocksize = enc->block_size; - plainlen = krb5_roundup(blocksize + input->length, blocksize); - - krb5int_dk_encrypt_length(enc, hash, input->length, &enclen); - - /* key->length, ivec will be tested in enc->encrypt. */ - - if (output->length < enclen) - return(KRB5_BAD_MSIZE); - - /* Allocate and set up plaintext and to-be-derived keys. */ - - plaintext = malloc(plainlen); - if (plaintext == NULL) - return ENOMEM; - - /* Derive the keys. */ - - d1.data = (char *) constantdata; - d1.length = K5CLENGTH; - - store_32_be(usage, constantdata); - - d1.data[4] = (char) 0xAA; - - ret = krb5int_derive_key(enc, key, &ke, &d1); - if (ret != 0) - goto cleanup; - - d1.data[4] = 0x55; - - ret = krb5int_derive_key(enc, key, &ki, &d1); - if (ret != 0) - goto cleanup; - - /* Put together the plaintext. */ - - d1.length = blocksize; - d1.data = (char *) plaintext; - - ret = krb5_c_random_make_octets(/* XXX */ 0, &d1); - if (ret != 0) - goto cleanup; - - memcpy(plaintext + blocksize, input->data, input->length); - - memset(plaintext + blocksize + input->length, 0, - plainlen - (blocksize + input->length)); - - /* Encrypt the plaintext. */ - - d1.length = plainlen; - d1.data = (char *) plaintext; - - d2.length = plainlen; - d2.data = output->data; - - ret = (*enc->encrypt)(ke, ivec, &d1, &d2); - if (ret != 0) - goto cleanup; - - if (ivec != NULL && ivec->length == blocksize) - cn = d2.data + d2.length - blocksize; - else - cn = NULL; - - /* Hash the plaintext. */ - - d2.length = enclen - plainlen; - d2.data = output->data+plainlen; - - output->length = enclen; - - ret = krb5int_hmac(hash, ki, 1, &d1, &d2); - if (ret != 0) { - memset(d2.data, 0, d2.length); - goto cleanup; - } - - /* Update ivec. */ - if (cn != NULL) - memcpy(ivec->data, cn, blocksize); - -cleanup: - krb5_k_free_key(NULL, ke); - krb5_k_free_key(NULL, ki); - zapfree(plaintext, plainlen); - return ret; -} - -/* Not necessarily "AES", per se, but "a CBC+CTS mode block cipher - with a 96-bit truncated HMAC". */ -void -krb5int_aes_encrypt_length(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - size_t inputlen, size_t *length) -{ - size_t blocksize, hashsize; - - blocksize = enc->block_size; - hashsize = 96 / 8; - - /* No roundup, since CTS requires no padding once we've hit the - block size. */ - *length = blocksize+inputlen + hashsize; -} - -static krb5_error_code -trunc_hmac (const struct krb5_hash_provider *hash, - krb5_key ki, unsigned int num, - const krb5_data *input, const krb5_data *output) -{ - size_t hashsize; - krb5_data tmp; - krb5_error_code ret; - - hashsize = hash->hashsize; - if (hashsize < output->length) - return KRB5_CRYPTO_INTERNAL; - tmp.length = hashsize; - tmp.data = malloc(hashsize); - if (tmp.data == NULL) - return ENOMEM; - ret = krb5int_hmac(hash, ki, num, input, &tmp); - if (ret == 0) - memcpy(output->data, tmp.data, output->length); - memset(tmp.data, 0, hashsize); - free(tmp.data); - return ret; -} - -krb5_error_code -krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - krb5_key key, krb5_keyusage usage, - const krb5_data *ivec, const krb5_data *input, - krb5_data *output) -{ - size_t blocksize, keybytes, plainlen, enclen; - krb5_error_code ret; - unsigned char constantdata[K5CLENGTH]; - krb5_data d1, d2; - unsigned char *plaintext = NULL; - char *cn; - krb5_key ke = NULL, ki = NULL; - - /* allocate and set up plaintext and to-be-derived keys */ - - blocksize = enc->block_size; - keybytes = enc->keybytes; - plainlen = blocksize+input->length; - - krb5int_aes_encrypt_length(enc, hash, input->length, &enclen); - - /* key->length, ivec will be tested in enc->encrypt */ - - if (output->length < enclen) - return KRB5_BAD_MSIZE; - - plaintext = malloc(plainlen); - if (plaintext == NULL) - return ENOMEM; - - /* Derive the keys. */ - - d1.data = (char *) constantdata; - d1.length = K5CLENGTH; - - store_32_be(usage, constantdata); - - d1.data[4] = (char) 0xAA; - - ret = krb5int_derive_key(enc, key, &ke, &d1); - if (ret != 0) - goto cleanup; - - d1.data[4] = 0x55; - - ret = krb5int_derive_key(enc, key, &ki, &d1); - if (ret != 0) - goto cleanup; - - /* put together the plaintext */ - - d1.length = blocksize; - d1.data = (char *) plaintext; - - ret = krb5_c_random_make_octets(NULL, &d1); - if (ret != 0) - goto cleanup; - - memcpy(plaintext + blocksize, input->data, input->length); - - /* Ciphertext stealing; there should be no more. */ - if (plainlen != blocksize + input->length) - abort(); - - /* Encrypt the plaintext. */ - - d1.length = plainlen; - d1.data = (char *) plaintext; - - d2.length = plainlen; - d2.data = output->data; - - ret = (*enc->encrypt)(ke, ivec, &d1, &d2); - if (ret != 0) - goto cleanup; - - if (ivec != NULL && ivec->length == blocksize) { - int nblocks = (d2.length + blocksize - 1) / blocksize; - cn = d2.data + blocksize * (nblocks - 2); - } else - cn = NULL; - - /* Hash the plaintext. */ - - d2.length = enclen - plainlen; - d2.data = output->data+plainlen; - if (d2.length != 96 / 8) - abort(); - - ret = trunc_hmac(hash, ki, 1, &d1, &d2); - if (ret != 0) { - memset(d2.data, 0, d2.length); - goto cleanup; - } - - output->length = enclen; - - /* Update ivec. */ - if (cn != NULL) - memcpy(ivec->data, cn, blocksize); - -cleanup: - krb5_k_free_key(NULL, ke); - krb5_k_free_key(NULL, ki); - zapfree(plaintext, plainlen); - return ret; -} diff --git a/src/lib/crypto/krb/dk/stringtokey.c b/src/lib/crypto/krb/dk/stringtokey.c index ff436e6..9a49187 100644 --- a/src/lib/crypto/krb/dk/stringtokey.c +++ b/src/lib/crypto/krb/dk/stringtokey.c @@ -31,10 +31,11 @@ static const unsigned char kerberos[] = "kerberos"; #define kerberos_len (sizeof(kerberos)-1) krb5_error_code -krb5int_dk_string_to_key(const struct krb5_enc_provider *enc, +krb5int_dk_string_to_key(const struct krb5_keytypes *ktp, const krb5_data *string, const krb5_data *salt, const krb5_data *parms, krb5_keyblock *keyblock) { + const struct krb5_enc_provider *enc = ktp->enc; krb5_error_code ret; size_t keybytes, keylength, concatlen; unsigned char *concat = NULL, *foldstring = NULL, *foldkeydata = NULL; @@ -72,7 +73,7 @@ krb5int_dk_string_to_key(const struct krb5_enc_provider *enc, foldkeyblock.length = keylength; foldkeyblock.contents = foldkeydata; - ret = (*enc->make_key)(&indata, &foldkeyblock); + ret = enc->make_key(&indata, &foldkeyblock); if (ret != 0) goto cleanup; @@ -96,3 +97,63 @@ cleanup: krb5_k_free_key(NULL, foldkey); return ret; } + + +#define DEFAULT_ITERATION_COUNT 4096 /* was 0xb000L in earlier drafts */ +#define MAX_ITERATION_COUNT 0x1000000L + +krb5_error_code +krb5int_aes_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key) +{ + unsigned long iter_count; + krb5_data out; + static const krb5_data usage = { KV5M_DATA, 8, "kerberos" }; + krb5_key tempkey = NULL; + krb5_error_code err; + + if (params) { + unsigned char *p = (unsigned char *) params->data; + if (params->length != 4) + return KRB5_ERR_BAD_S2K_PARAMS; + /* The first two need casts in case 'int' is 16 bits. */ + iter_count = load_32_be(p); + if (iter_count == 0) { + iter_count = (1UL << 16) << 16; + if (((iter_count >> 16) >> 16) != 1) + return KRB5_ERR_BAD_S2K_PARAMS; + } + } else + iter_count = DEFAULT_ITERATION_COUNT; + + /* This is not a protocol specification constraint; this is an + implementation limit, which should eventually be controlled by + a config file. */ + if (iter_count >= MAX_ITERATION_COUNT) + return KRB5_ERR_BAD_S2K_PARAMS; + + /* Use the output keyblock contents for temporary space. */ + out.data = (char *) key->contents; + out.length = key->length; + if (out.length != 16 && out.length != 32) + return KRB5_CRYPTO_INTERNAL; + + err = krb5int_pbkdf2_hmac_sha1 (&out, iter_count, string, salt); + if (err) + goto cleanup; + + err = krb5_k_create_key (NULL, key, &tempkey); + if (err) + goto cleanup; + + err = krb5int_derive_keyblock(ktp->enc, tempkey, key, &usage); + +cleanup: + if (err) + memset (out.data, 0, out.length); + krb5_k_free_key (NULL, tempkey); + return err; +} -- cgit v1.1