diff options
author | Greg Hudson <ghudson@mit.edu> | 2009-11-30 16:19:24 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2009-11-30 16:19:24 +0000 |
commit | 2b02e102d3c4e3bb54c936d301371d6b3d88cb52 (patch) | |
tree | d9ae2f2202a2a62b2e727167adbfb4fdfa3d4be1 /src/lib/crypto/krb/old | |
parent | c54198be3feb7c98aa632be7d4bf56e6002cfffc (diff) | |
download | krb5-2b02e102d3c4e3bb54c936d301371d6b3d88cb52.zip krb5-2b02e102d3c4e3bb54c936d301371d6b3d88cb52.tar.gz krb5-2b02e102d3c4e3bb54c936d301371d6b3d88cb52.tar.bz2 |
Add an AEAD provider for enctypes which use krb5_old_encrypt and
krb5_old_decrypt; this makes every enctype have an AEAD provider. To
make this work, expose make_unkeyed_checksum_iov to other files (under
the name krb5int_hash_iov) and make krb5int_c_padding_length take into
account the header length.
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23388 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/crypto/krb/old')
-rw-r--r-- | src/lib/crypto/krb/old/Makefile.in | 10 | ||||
-rw-r--r-- | src/lib/crypto/krb/old/old.h | 2 | ||||
-rw-r--r-- | src/lib/crypto/krb/old/old_aead.c | 209 |
3 files changed, 216 insertions, 5 deletions
diff --git a/src/lib/crypto/krb/old/Makefile.in b/src/lib/crypto/krb/old/Makefile.in index ea704cc..aadeacc 100644 --- a/src/lib/crypto/krb/old/Makefile.in +++ b/src/lib/crypto/krb/old/Makefile.in @@ -1,6 +1,6 @@ mydir=lib/crypto/krb/old BUILDTOP=$(REL)..$(S)..$(S)..$(S).. -LOCALINCLUDES = -I$(srcdir)/../../@CRYPTO_IMPL@/des -I$(srcdir) +LOCALINCLUDES = -I$(srcdir)/../../@CRYPTO_IMPL@/des -I$(srcdir)/.. -I$(srcdir) DEFS= ##DOS##BUILDTOP = ..\..\.. @@ -12,12 +12,12 @@ PROG_RPATH=$(KRB5_LIBDIR) RUN_SETUP = @KRB5_RUN_ENV@ KRB5_CONFIG=$(top_srcdir)/config-files/krb5.conf -STLIBOBJS= old_decrypt.o old_encrypt.o des_stringtokey.o +STLIBOBJS= old_aead.o old_decrypt.o old_encrypt.o des_stringtokey.o -OBJS= $(OUTPRE)des_stringtokey.$(OBJEXT) $(OUTPRE)old_decrypt.$(OBJEXT) $(OUTPRE)old_encrypt.$(OBJEXT) +OBJS= $(OUTPRE)des_stringtokey.$(OBJEXT) $(OUTPRE)old_aead.$(OBJEXT) $(OUTPRE)old_decrypt.$(OBJEXT) $(OUTPRE)old_encrypt.$(OBJEXT) -SRCS= $(srcdir)/des_stringtokey.c $(srcdir)/old_decrypt.c \ - $(srcdir)/old_encrypt.c +SRCS= $(srcdir)/des_stringtokey.c $(srcdir)/old_aead.c \ + $(srcdir)/old_decrypt.c $(srcdir)/old_encrypt.c ##DOS##LIBOBJS = $(OBJS) diff --git a/src/lib/crypto/krb/old/old.h b/src/lib/crypto/krb/old/old.h index 1ed19a0..58f4f5a 100644 --- a/src/lib/crypto/krb/old/old.h +++ b/src/lib/crypto/krb/old/old.h @@ -49,3 +49,5 @@ krb5_error_code krb5int_des_string_to_key(const struct krb5_enc_provider *enc, const krb5_data *salt, const krb5_data *params, krb5_keyblock *key); + +extern const struct krb5_aead_provider krb5int_aead_old; diff --git a/src/lib/crypto/krb/old/old_aead.c b/src/lib/crypto/krb/old/old_aead.c new file mode 100644 index 0000000..3dea3c3 --- /dev/null +++ b/src/lib/crypto/krb/old/old_aead.c @@ -0,0 +1,209 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * lib/crypto/old/old_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 "old.h" +#include "aead.h" + +static krb5_error_code +krb5int_old_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 + hash->hashsize; + break; + case KRB5_CRYPTO_TYPE_PADDING: + *length = enc->block_size; + break; + case KRB5_CRYPTO_TYPE_TRAILER: + *length = 0; + break; + case KRB5_CRYPTO_TYPE_CHECKSUM: + *length = hash->hashsize; + break; + default: + assert(0 && "invalid cryptotype passed to krb5int_old_crypto_length"); + break; + } + + return 0; +} + +static krb5_error_code +krb5int_old_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 ret; + krb5_crypto_iov *header, *trailer, *padding; + krb5_data checksum, confounder, crcivec = empty_data(); + unsigned int plainlen, padsize; + size_t i; + + /* E(Confounder | Checksum | Plaintext | Pad) */ + + plainlen = enc->block_size + hash->hashsize; + for (i = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (iov->flags == KRB5_CRYPTO_TYPE_DATA) + plainlen += iov->data.length; + } + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length < enc->block_size + hash->hashsize) + return KRB5_BAD_MSIZE; + + /* Trailer may be absent. */ + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL) + trailer->data.length = 0; + + /* Check that the input data is correctly padded. */ + padsize = krb5_roundup(plainlen, enc->block_size) - plainlen; + padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING); + if (padsize > 0 && (padding == NULL || padding->data.length < padsize)) + return KRB5_BAD_MSIZE; + if (padding) { + padding->data.length = padsize; + memset(padding->data.data, 0, padsize); + } + + /* Generate a confounder in the header block. */ + confounder = make_data(header->data.data, enc->block_size); + ret = krb5_c_random_make_octets(0, &confounder); + if (ret != 0) + goto cleanup; + checksum = make_data(header->data.data + enc->block_size, hash->hashsize); + memset(checksum.data, 0, hash->hashsize); + + /* Checksum the plaintext with zeroed checksum and padding. */ + ret = krb5int_hash_iov(hash, data, num_data, &checksum); + if (ret != 0) + goto cleanup; + + /* Use the key as the ivec for des-cbc-crc if none was provided. */ + if (key->keyblock.enctype == ENCTYPE_DES_CBC_CRC && ivec == NULL) { + ret = alloc_data(&crcivec, key->keyblock.length); + memcpy(crcivec.data, key->keyblock.contents, key->keyblock.length); + ivec = &crcivec; + } + + ret = enc->encrypt_iov(key, ivec, data, num_data); + if (ret != 0) + goto cleanup; + +cleanup: + zapfree(crcivec.data, crcivec.length); + return ret; +} + +static krb5_error_code +krb5int_old_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 ret; + krb5_crypto_iov *header, *trailer; + krb5_data checksum, crcivec = empty_data(); + char *saved_checksum = NULL; + size_t i; + unsigned int cipherlen = 0; + + /* Check that the input data is correctly padded. */ + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_IOV(iov)) + cipherlen += iov->data.length; + } + if (cipherlen % enc->block_size != 0) + return KRB5_BAD_MSIZE; + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length != enc->block_size + hash->hashsize) + return KRB5_BAD_MSIZE; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL && trailer->data.length != 0) + return KRB5_BAD_MSIZE; + + /* Use the key as the ivec for des-cbc-crc if none was provided. */ + if (key->keyblock.enctype == ENCTYPE_DES_CBC_CRC && ivec == NULL) { + ret = alloc_data(&crcivec, key->keyblock.length); + memcpy(crcivec.data, key->keyblock.contents, key->keyblock.length); + ivec = &crcivec; + } + + /* Decrypt the ciphertext. */ + ret = enc->decrypt_iov(key, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + /* Save the checksum, then zero it out in the plaintext. */ + checksum = make_data(header->data.data + enc->block_size, hash->hashsize); + saved_checksum = k5alloc(hash->hashsize, &ret); + if (saved_checksum == NULL) + goto cleanup; + memcpy(saved_checksum, checksum.data, checksum.length); + memset(checksum.data, 0, checksum.length); + + /* + * Checksum the plaintext (with zeroed checksum field), storing the result + * back into the plaintext field we just zeroed out. Then compare it to + * the saved checksum. + */ + ret = krb5int_hash_iov(hash, data, num_data, &checksum); + if (memcmp(checksum.data, saved_checksum, checksum.length) != 0) { + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + +cleanup: + zapfree(crcivec.data, crcivec.length); + zapfree(saved_checksum, hash->hashsize); + return ret; +} + +const struct krb5_aead_provider krb5int_aead_old = { + krb5int_old_crypto_length, + krb5int_old_encrypt_iov, + krb5int_old_decrypt_iov +}; |