diff options
Diffstat (limited to 'src/lib/crypto/krb')
70 files changed, 10096 insertions, 0 deletions
diff --git a/src/lib/crypto/krb/Makefile.in b/src/lib/crypto/krb/Makefile.in new file mode 100644 index 000000000000..c5660c5fe1fa --- /dev/null +++ b/src/lib/crypto/krb/Makefile.in @@ -0,0 +1,227 @@ +mydir=lib$(S)crypto$(S)krb +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/../$(CRYPTO_IMPL) + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR = krb +##DOS##OBJFILE = ..\$(OUTPRE)krb.lst + +STLIBOBJS=\ + aead.o \ + block_size.o \ + cf2.o \ + checksum_cbc.o \ + checksum_confounder.o \ + checksum_dk_cmac.o \ + checksum_dk_hmac.o \ + checksum_etm.o \ + checksum_hmac_md5.o \ + checksum_unkeyed.o \ + checksum_length.o \ + cksumtype_to_string.o \ + cksumtypes.o \ + cmac.o \ + coll_proof_cksum.o \ + combine_keys.o \ + crc32.o \ + crypto_length.o \ + crypto_libinit.o \ + default_state.o \ + decrypt.o \ + decrypt_iov.o \ + derive.o \ + encrypt.o \ + encrypt_iov.o \ + encrypt_length.o \ + enctype_util.o \ + enc_dk_cmac.o \ + enc_dk_hmac.o \ + enc_etm.o \ + enc_old.o \ + enc_raw.o \ + enc_rc4.o \ + etypes.o \ + key.o \ + keyblocks.o \ + keyed_cksum.o \ + keyed_checksum_types.o \ + keylengths.o \ + make_checksum.o \ + make_checksum_iov.o \ + make_random_key.o \ + mandatory_sumtype.o \ + nfold.o \ + old_api_glue.o \ + prf.o \ + prf_aes2.o \ + prf_cmac.o \ + prf_des.o \ + prf_dk.o \ + prf_rc4.o \ + prng.o \ + prng_$(PRNG_ALG).o \ + random_to_key.o \ + s2k_des.o \ + s2k_pbkdf2.o \ + s2k_rc4.o \ + state.o \ + string_to_cksumtype.o \ + string_to_key.o \ + valid_cksumtype.o \ + verify_checksum.o \ + verify_checksum_iov.o + +OBJS=\ + $(OUTPRE)aead.$(OBJEXT) \ + $(OUTPRE)block_size.$(OBJEXT) \ + $(OUTPRE)cf2.$(OBJEXT) \ + $(OUTPRE)checksum_cbc.$(OBJEXT) \ + $(OUTPRE)checksum_confounder.$(OBJEXT) \ + $(OUTPRE)checksum_dk_cmac.$(OBJEXT) \ + $(OUTPRE)checksum_dk_hmac.$(OBJEXT) \ + $(OUTPRE)checksum_etm.$(OBJEXT) \ + $(OUTPRE)checksum_hmac_md5.$(OBJEXT) \ + $(OUTPRE)checksum_unkeyed.$(OBJEXT) \ + $(OUTPRE)checksum_length.$(OBJEXT) \ + $(OUTPRE)cksumtype_to_string.$(OBJEXT) \ + $(OUTPRE)cksumtypes.$(OBJEXT) \ + $(OUTPRE)cmac.$(OBJEXT) \ + $(OUTPRE)coll_proof_cksum.$(OBJEXT) \ + $(OUTPRE)combine_keys.$(OBJEXT) \ + $(OUTPRE)crc32.$(OBJEXT) \ + $(OUTPRE)crypto_length.$(OBJEXT) \ + $(OUTPRE)crypto_libinit.$(OBJEXT) \ + $(OUTPRE)default_state.$(OBJEXT) \ + $(OUTPRE)decrypt.$(OBJEXT) \ + $(OUTPRE)decrypt_iov.$(OBJEXT) \ + $(OUTPRE)derive.$(OBJEXT) \ + $(OUTPRE)encrypt.$(OBJEXT) \ + $(OUTPRE)encrypt_iov.$(OBJEXT) \ + $(OUTPRE)encrypt_length.$(OBJEXT) \ + $(OUTPRE)enctype_util.$(OBJEXT) \ + $(OUTPRE)enc_dk_cmac.$(OBJEXT) \ + $(OUTPRE)enc_dk_hmac.$(OBJEXT) \ + $(OUTPRE)enc_etm.$(OBJEXT) \ + $(OUTPRE)enc_old.$(OBJEXT) \ + $(OUTPRE)enc_raw.$(OBJEXT) \ + $(OUTPRE)enc_rc4.$(OBJEXT) \ + $(OUTPRE)etypes.$(OBJEXT) \ + $(OUTPRE)key.$(OBJEXT) \ + $(OUTPRE)keyblocks.$(OBJEXT) \ + $(OUTPRE)keyed_cksum.$(OBJEXT) \ + $(OUTPRE)keyed_checksum_types.$(OBJEXT) \ + $(OUTPRE)keylengths.$(OBJEXT) \ + $(OUTPRE)make_checksum.$(OBJEXT) \ + $(OUTPRE)make_checksum_iov.$(OBJEXT) \ + $(OUTPRE)make_random_key.$(OBJEXT) \ + $(OUTPRE)mandatory_sumtype.$(OBJEXT) \ + $(OUTPRE)nfold.$(OBJEXT) \ + $(OUTPRE)old_api_glue.$(OBJEXT) \ + $(OUTPRE)prf.$(OBJEXT) \ + $(OUTPRE)prf_aes2.$(OBJEXT) \ + $(OUTPRE)prf_cmac.$(OBJEXT) \ + $(OUTPRE)prf_des.$(OBJEXT) \ + $(OUTPRE)prf_dk.$(OBJEXT) \ + $(OUTPRE)prf_rc4.$(OBJEXT) \ + $(OUTPRE)prng.$(OBJEXT) \ + $(OUTPRE)prng_$(PRNG_ALG).$(OBJEXT) \ + $(OUTPRE)random_to_key.$(OBJEXT) \ + $(OUTPRE)s2k_des.$(OBJEXT) \ + $(OUTPRE)s2k_pbkdf2.$(OBJEXT) \ + $(OUTPRE)s2k_rc4.$(OBJEXT) \ + $(OUTPRE)state.$(OBJEXT) \ + $(OUTPRE)string_to_cksumtype.$(OBJEXT) \ + $(OUTPRE)string_to_key.$(OBJEXT) \ + $(OUTPRE)valid_cksumtype.$(OBJEXT) \ + $(OUTPRE)verify_checksum.$(OBJEXT) \ + $(OUTPRE)verify_checksum_iov.$(OBJEXT) + +SRCS=\ + $(srcdir)/aead.c \ + $(srcdir)/block_size.c \ + $(srcdir)/cf2.c \ + $(srcdir)/checksum_cbc.c \ + $(srcdir)/checksum_confounder.c \ + $(srcdir)/checksum_dk_cmac.c \ + $(srcdir)/checksum_dk_hmac.c \ + $(srcdir)/checksum_etm.c \ + $(srcdir)/checksum_hmac_md5.c \ + $(srcdir)/checksum_unkeyed.c \ + $(srcdir)/checksum_length.c \ + $(srcdir)/cksumtype_to_string.c \ + $(srcdir)/cksumtypes.c \ + $(srcdir)/cmac.c \ + $(srcdir)/coll_proof_cksum.c \ + $(srcdir)/combine_keys.c \ + $(srcdir)/crc32.c \ + $(srcdir)/crypto_length.c \ + $(srcdir)/crypto_libinit.c \ + $(srcdir)/default_state.c \ + $(srcdir)/decrypt.c \ + $(srcdir)/decrypt_iov.c \ + $(srcdir)/derive.c \ + $(srcdir)/encrypt.c \ + $(srcdir)/encrypt_iov.c \ + $(srcdir)/encrypt_length.c \ + $(srcdir)/enctype_util.c \ + $(srcdir)/enc_dk_cmac.c \ + $(srcdir)/enc_dk_hmac.c \ + $(srcdir)/enc_etm.c \ + $(srcdir)/enc_old.c \ + $(srcdir)/enc_raw.c \ + $(srcdir)/enc_rc4.c \ + $(srcdir)/etypes.c \ + $(srcdir)/key.c \ + $(srcdir)/keyblocks.c \ + $(srcdir)/keyed_cksum.c \ + $(srcdir)/keyed_checksum_types.c\ + $(srcdir)/keylengths.c \ + $(srcdir)/make_checksum.c \ + $(srcdir)/make_checksum_iov.c \ + $(srcdir)/make_random_key.c \ + $(srcdir)/mandatory_sumtype.c \ + $(srcdir)/nfold.c \ + $(srcdir)/old_api_glue.c \ + $(srcdir)/prf.c \ + $(srcdir)/prf_aes2.c \ + $(srcdir)/prf_cmac.c \ + $(srcdir)/prf_des.c \ + $(srcdir)/prf_dk.c \ + $(srcdir)/prf_rc4.c \ + $(srcdir)/prng.c \ + $(srcdir)/prng_$(PRNG_ALG).c \ + $(srcdir)/cf2.c \ + $(srcdir)/random_to_key.c \ + $(srcdir)/s2k_des.c \ + $(srcdir)/s2k_pbkdf2.c \ + $(srcdir)/s2k_rc4.c \ + $(srcdir)/state.c \ + $(srcdir)/string_to_cksumtype.c \ + $(srcdir)/string_to_key.c \ + $(srcdir)/t_fortuna.c \ + $(srcdir)/valid_cksumtype.c \ + $(srcdir)/verify_checksum.c \ + $(srcdir)/verify_checksum_iov.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs +includes: depend + +depend: $(SRCS) + +check-unix: t_fortuna + if [ $(PRNG_ALG) = fortuna ]; then \ + $(RUN_TEST) ./t_fortuna > t_fortuna.output; \ + cmp t_fortuna.output $(srcdir)/t_fortuna.expected; \ + fi + +t_fortuna: t_fortuna.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB) + $(CC_LINK) -o $@ t_fortuna.o $(K5CRYPTO_LIB) $(SUPPORT_LIB) $(LIBS) + +clean-unix:: clean-libobjs + $(RM) t_fortuna.o t_fortuna t_fortuna.output + +@lib_frag@ +@libobj_frag@ + diff --git a/src/lib/crypto/krb/aead.c b/src/lib/crypto/krb/aead.c new file mode 100644 index 000000000000..9d4e206ab77c --- /dev/null +++ b/src/lib/crypto/krb/aead.c @@ -0,0 +1,223 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/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 "crypto_int.h" + +krb5_crypto_iov * +krb5int_c_locate_iov(krb5_crypto_iov *data, size_t num_data, + krb5_cryptotype type) +{ + size_t i; + krb5_crypto_iov *iov = NULL; + + if (data == NULL) + return NULL; + + for (i = 0; i < num_data; i++) { + if (data[i].flags == type) { + if (iov == NULL) + iov = &data[i]; + else + return NULL; /* can't appear twice */ + } + } + + return iov; +} + +krb5_error_code +krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage keyusage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + krb5_error_code ret; + unsigned int header_len, trailer_len; + krb5_crypto_iov *iov; + krb5_crypto_iov *stream; + size_t i, j; + int got_data = 0; + + stream = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_STREAM); + assert(stream != NULL); + + header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + + if (stream->data.length < header_len + trailer_len) + return KRB5_BAD_MSIZE; + + iov = calloc(num_data + 2, sizeof(krb5_crypto_iov)); + if (iov == NULL) + return ENOMEM; + + i = 0; + + iov[i].flags = KRB5_CRYPTO_TYPE_HEADER; /* takes place of STREAM */ + iov[i].data = make_data(stream->data.data, header_len); + i++; + + for (j = 0; j < num_data; j++) { + if (data[j].flags == KRB5_CRYPTO_TYPE_DATA) { + if (got_data) { + free(iov); + return KRB5_BAD_MSIZE; + } + + got_data++; + + data[j].data.data = stream->data.data + header_len; + data[j].data.length = stream->data.length - header_len + - trailer_len; + } + if (data[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY || + data[j].flags == KRB5_CRYPTO_TYPE_DATA) + iov[i++] = data[j]; + } + + /* Use empty padding since tokens don't indicate the padding length. */ + iov[i].flags = KRB5_CRYPTO_TYPE_PADDING; + iov[i].data = empty_data(); + i++; + + iov[i].flags = KRB5_CRYPTO_TYPE_TRAILER; + iov[i].data = make_data(stream->data.data + stream->data.length - + trailer_len, trailer_len); + i++; + + assert(i <= num_data + 2); + + ret = ktp->decrypt(ktp, key, keyusage, ivec, iov, i); + free(iov); + return ret; +} + +unsigned int +krb5int_c_padding_length(const struct krb5_keytypes *ktp, size_t data_length) +{ + unsigned int header, padding; + + /* + * Add in the header length since the header is encrypted along with the + * data. (arcfour violates this assumption since not all of the header is + * encrypted, but that's okay since it has no padding. If there is ever an + * enctype using a similar token format and a block cipher, we will have to + * move this logic into an enctype-dependent function.) + */ + header = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); + data_length += header; + + padding = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING); + if (padding == 0 || (data_length % padding) == 0) + return 0; + else + return padding - (data_length % padding); +} + +/* Return the next iov (starting from ind) which cursor should process, or + * cursor->iov_count if there are none remaining. */ +static size_t +next_iov_to_process(struct iov_cursor *cursor, size_t ind) +{ + const krb5_crypto_iov *iov; + + for (; ind < cursor->iov_count; ind++) { + iov = &cursor->iov[ind]; + if (cursor->signing ? SIGN_IOV(iov) : ENCRYPT_IOV(iov)) + break; + } + return ind; +} + +void +k5_iov_cursor_init(struct iov_cursor *cursor, const krb5_crypto_iov *iov, + size_t count, size_t block_size, krb5_boolean signing) +{ + cursor->iov = iov; + cursor->iov_count = count; + cursor->block_size = block_size; + cursor->signing = signing; + cursor->in_iov = next_iov_to_process(cursor, 0); + cursor->out_iov = cursor->in_iov; + cursor->in_pos = cursor->out_pos = 0; +} + +/* Fetch one block from cursor's input position. */ +krb5_boolean +k5_iov_cursor_get(struct iov_cursor *cursor, unsigned char *block) +{ + size_t nbytes, bsz = cursor->block_size, remain = cursor->block_size; + const krb5_crypto_iov *iov; + + remain = cursor->block_size; + while (remain > 0 && cursor->in_iov < cursor->iov_count) { + iov = &cursor->iov[cursor->in_iov]; + + nbytes = iov->data.length - cursor->in_pos; + if (nbytes > remain) + nbytes = remain; + + memcpy(block + bsz - remain, iov->data.data + cursor->in_pos, nbytes); + cursor->in_pos += nbytes; + remain -= nbytes; + + if (cursor->in_pos == iov->data.length) { + cursor->in_iov = next_iov_to_process(cursor, cursor->in_iov + 1); + cursor->in_pos = 0; + } + } + + if (remain == bsz) + return FALSE; + if (remain > 0) + memset(block + bsz - remain, 0, remain); + return TRUE; +} + +/* Write a block to a cursor's output position. */ +void +k5_iov_cursor_put(struct iov_cursor *cursor, unsigned char *block) +{ + size_t nbytes, bsz = cursor->block_size, remain = cursor->block_size; + const krb5_crypto_iov *iov; + + remain = cursor->block_size; + while (remain > 0 && cursor->out_iov < cursor->iov_count) { + iov = &cursor->iov[cursor->out_iov]; + + nbytes = iov->data.length - cursor->out_pos; + if (nbytes > remain) + nbytes = remain; + + memcpy(iov->data.data + cursor->out_pos, block + bsz - remain, nbytes); + cursor->out_pos += nbytes; + remain -= nbytes; + + if (cursor->out_pos == iov->data.length) { + cursor->out_iov = next_iov_to_process(cursor, cursor->out_iov + 1); + cursor->out_pos = 0; + } + } +} diff --git a/src/lib/crypto/krb/block_size.c b/src/lib/crypto/krb/block_size.c new file mode 100644 index 000000000000..d50c94469b35 --- /dev/null +++ b/src/lib/crypto/krb/block_size.c @@ -0,0 +1,42 @@ +/* -*- 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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_block_size(krb5_context context, krb5_enctype enctype, + size_t *blocksize) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + *blocksize = ktp->enc->block_size; + + return 0; +} diff --git a/src/lib/crypto/krb/cf2.c b/src/lib/crypto/krb/cf2.c new file mode 100644 index 000000000000..2ee5aebda3f5 --- /dev/null +++ b/src/lib/crypto/krb/cf2.c @@ -0,0 +1,176 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/cf2.c */ +/* + * Copyright (C) 2009, 2015 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. + */ + +/* + * Implement KRB_FX_CF2 function per draft-ietf-krb-wg-preauth-framework-09. + * Take two keys and two pepper strings as input and return a combined key. + */ + +#include "crypto_int.h" + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +krb5_error_code KRB5_CALLCONV +krb5_c_prfplus(krb5_context context, const krb5_keyblock *k, + const krb5_data *input, krb5_data *output) +{ + krb5_error_code ret; + krb5_data prf_in = empty_data(), prf_out = empty_data(); + size_t prflen, nblocks, i; + + /* Calculate the number of PRF invocations we will need. */ + ret = krb5_c_prf_length(context, k->enctype, &prflen); + if (ret) + return ret; + nblocks = (output->length + prflen - 1)/ prflen; + if (nblocks > 255) + return E2BIG; + + /* Allocate PRF input and output buffers. */ + ret = alloc_data(&prf_in, input->length + 1); + if (ret) + goto cleanup; + ret = alloc_data(&prf_out, prflen); + if (ret) + goto cleanup; + + /* Concatenate PRF(k, 1||input) || PRF(k, 2||input) || ... to produce the + * desired number of bytes. */ + memcpy(&prf_in.data[1], input->data, input->length); + for (i = 0; i < nblocks; i++) { + prf_in.data[0] = i + 1; + ret = krb5_c_prf(context, k, &prf_in, &prf_out); + if (ret) + goto cleanup; + + memcpy(&output->data[i * prflen], prf_out.data, + MIN(prflen, output->length - i * prflen)); + } + +cleanup: + zapfree(prf_out.data, prf_out.length); + zapfree(prf_in.data, prf_in.length); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_derive_prfplus(krb5_context context, const krb5_keyblock *k, + const krb5_data *input, krb5_enctype enctype, + krb5_keyblock **out) +{ + krb5_error_code ret; + const struct krb5_keytypes *ktp; + krb5_data rnd = empty_data(); + krb5_keyblock *kb = NULL; + + *out = NULL; + + ktp = find_enctype((enctype == ENCTYPE_NULL) ? k->enctype : enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + /* Generate enough pseudo-random bytes for the random-to-key function. */ + ret = alloc_data(&rnd, ktp->enc->keybytes); + if (ret) + goto cleanup; + ret = krb5_c_prfplus(context, k, input, &rnd); + if (ret) + goto cleanup; + + /* Generate a key from the pseudo-random bytes. */ + ret = krb5int_c_init_keyblock(context, ktp->etype, ktp->enc->keylength, + &kb); + if (ret) + goto cleanup; + ret = (*ktp->rand2key)(&rnd, kb); + if (ret) + goto cleanup; + + *out = kb; + kb = NULL; + +cleanup: + zapfree(rnd.data, rnd.length); + krb5int_c_free_keyblock(context, kb); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_fx_cf2_simple(krb5_context context, + const krb5_keyblock *k1, const char *pepper1, + const krb5_keyblock *k2, const char *pepper2, + krb5_keyblock **out) +{ + krb5_error_code ret; + const struct krb5_keytypes *ktp = NULL; + const krb5_data pepper1_data = string2data((char *)pepper1); + const krb5_data pepper2_data = string2data((char *)pepper2); + krb5_data prf1 = empty_data(), prf2 = empty_data(); + unsigned int i; + krb5_keyblock *kb = NULL; + + *out = NULL; + + ktp = find_enctype(k1->enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + /* Generate PRF+(k1, pepper1) and PRF+(k2, kepper2). */ + ret = alloc_data(&prf1, ktp->enc->keybytes); + if (ret) + goto cleanup; + ret = krb5_c_prfplus(context, k1, &pepper1_data, &prf1); + if (ret) + goto cleanup; + ret = alloc_data(&prf2, ktp->enc->keybytes); + if (ret) + goto cleanup; + ret = krb5_c_prfplus(context, k2, &pepper2_data, &prf2); + if (ret) + goto cleanup; + + /* Compute the XOR of the two PRF+ values and generate a key. */ + for (i = 0; i < prf1.length; i++) + prf1.data[i] ^= prf2.data[i]; + ret = krb5int_c_init_keyblock(context, ktp->etype, ktp->enc->keylength, + &kb); + if (ret) + goto cleanup; + ret = (*ktp->rand2key)(&prf1, kb); + if (ret) + goto cleanup; + + *out = kb; + kb = NULL; + +cleanup: + zapfree(prf2.data, prf2.length); + zapfree(prf1.data, prf1.length); + krb5int_c_free_keyblock(context, kb); + return ret; +} diff --git a/src/lib/crypto/krb/checksum_cbc.c b/src/lib/crypto/krb/checksum_cbc.c new file mode 100644 index 000000000000..48afeb0e5cc6 --- /dev/null +++ b/src/lib/crypto/krb/checksum_cbc.c @@ -0,0 +1,41 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/checksum_cbc.c */ +/* + * Copyright (C) 2009 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. + */ + +/* CBC checksum, which computes the ivec resulting from CBC encryption of the + * input. */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_cbc_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + if (ctp->enc->cbc_mac == NULL) + return KRB5_CRYPTO_INTERNAL; + return ctp->enc->cbc_mac(key, data, num_data, NULL, output); +} diff --git a/src/lib/crypto/krb/checksum_confounder.c b/src/lib/crypto/krb/checksum_confounder.c new file mode 100644 index 000000000000..34941562c416 --- /dev/null +++ b/src/lib/crypto/krb/checksum_confounder.c @@ -0,0 +1,159 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/checksum_confounder.c */ +/* + * Copyright (C) 2009 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. + */ + +/* + * Confounder checksum implementation, using tokens of the form: + * enc(xorkey, confounder | hash(confounder | data)) + * where xorkey is the key XOR'd with 0xf0 bytes. + */ + +#include "crypto_int.h" + +/* Derive a key by XOR with 0xF0 bytes. */ +static krb5_error_code +mk_xorkey(krb5_key origkey, krb5_key *xorkey) +{ + krb5_error_code retval = 0; + unsigned char *xorbytes; + krb5_keyblock xorkeyblock; + size_t i = 0; + + xorbytes = k5memdup(origkey->keyblock.contents, origkey->keyblock.length, + &retval); + if (xorbytes == NULL) + return retval; + for (i = 0; i < origkey->keyblock.length; i++) + xorbytes[i] ^= 0xf0; + + /* Do a shallow copy here. */ + xorkeyblock = origkey->keyblock; + xorkeyblock.contents = xorbytes; + + retval = krb5_k_create_key(0, &xorkeyblock, xorkey); + zapfree(xorbytes, origkey->keyblock.length); + return retval; +} + +krb5_error_code +krb5int_confounder_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + krb5_error_code ret; + krb5_data conf, hashval; + krb5_key xorkey = NULL; + krb5_crypto_iov *hash_iov, iov; + size_t blocksize = ctp->enc->block_size, hashsize = ctp->hash->hashsize; + + /* Partition the output buffer into confounder and hash. */ + conf = make_data(output->data, blocksize); + hashval = make_data(output->data + blocksize, hashsize); + + /* Create the confounder. */ + ret = krb5_c_random_make_octets(NULL, &conf); + if (ret != 0) + return ret; + + ret = mk_xorkey(key, &xorkey); + if (ret) + return ret; + + /* Hash the confounder, then the input data. */ + hash_iov = k5calloc(num_data + 1, sizeof(krb5_crypto_iov), &ret); + if (hash_iov == NULL) + goto cleanup; + hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + hash_iov[0].data = conf; + memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov)); + ret = ctp->hash->hash(hash_iov, num_data + 1, &hashval); + if (ret != 0) + goto cleanup; + + /* Confounder and hash are in output buffer; encrypt them in place. */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *output; + ret = ctp->enc->encrypt(xorkey, NULL, &iov, 1); + +cleanup: + free(hash_iov); + krb5_k_free_key(NULL, xorkey); + return ret; +} + +krb5_error_code krb5int_confounder_verify(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + const krb5_data *input, + krb5_boolean *valid) +{ + krb5_error_code ret; + unsigned char *plaintext = NULL; + krb5_key xorkey = NULL; + krb5_data computed = empty_data(); + krb5_crypto_iov *hash_iov = NULL, iov; + size_t blocksize = ctp->enc->block_size, hashsize = ctp->hash->hashsize; + + plaintext = k5memdup(input->data, input->length, &ret); + if (plaintext == NULL) + return ret; + + ret = mk_xorkey(key, &xorkey); + if (ret != 0) + goto cleanup; + + /* Decrypt the input checksum. */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data(plaintext, input->length); + ret = ctp->enc->decrypt(xorkey, NULL, &iov, 1); + if (ret != 0) + goto cleanup; + + /* Hash the confounder, then the input data. */ + hash_iov = k5calloc(num_data + 1, sizeof(krb5_crypto_iov), &ret); + if (hash_iov == NULL) + goto cleanup; + hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + hash_iov[0].data = make_data(plaintext, blocksize); + memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov)); + ret = alloc_data(&computed, hashsize); + if (ret != 0) + goto cleanup; + ret = ctp->hash->hash(hash_iov, num_data + 1, &computed); + if (ret != 0) + goto cleanup; + + /* Compare the decrypted hash to the computed one. */ + *valid = (k5_bcmp(plaintext + blocksize, computed.data, hashsize) == 0); + +cleanup: + zapfree(plaintext, input->length); + zapfree(computed.data, hashsize); + free(hash_iov); + krb5_k_free_key(NULL, xorkey); + return ret; +} diff --git a/src/lib/crypto/krb/checksum_dk_cmac.c b/src/lib/crypto/krb/checksum_dk_cmac.c new file mode 100644 index 000000000000..809f9d729b41 --- /dev/null +++ b/src/lib/crypto/krb/checksum_dk_cmac.c @@ -0,0 +1,59 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/checksum_dk_cmac.c */ +/* + * Copyright 2010 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 "crypto_int.h" + +#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ + +krb5_error_code +krb5int_dk_cmac_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + const struct krb5_enc_provider *enc = ctp->enc; + krb5_error_code ret; + unsigned char constantdata[K5CLENGTH]; + krb5_data datain; + krb5_key kc; + + /* Derive the key. */ + datain = make_data(constantdata, K5CLENGTH); + store_32_be(usage, constantdata); + constantdata[4] = (char) 0x99; + ret = krb5int_derive_key(enc, NULL, key, &kc, &datain, + DERIVE_SP800_108_CMAC); + if (ret != 0) + return ret; + + /* Hash the data. */ + ret = krb5int_cmac_checksum(enc, kc, data, num_data, output); + if (ret != 0) + memset(output->data, 0, output->length); + + krb5_k_free_key(NULL, kc); + return ret; +} diff --git a/src/lib/crypto/krb/checksum_dk_hmac.c b/src/lib/crypto/krb/checksum_dk_hmac.c new file mode 100644 index 000000000000..64ab8993e838 --- /dev/null +++ b/src/lib/crypto/krb/checksum_dk_hmac.c @@ -0,0 +1,59 @@ +/* -*- 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 "crypto_int.h" + +#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ + +krb5_error_code +krb5int_dk_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + const struct krb5_enc_provider *enc = ctp->enc; + krb5_error_code ret; + unsigned char constantdata[K5CLENGTH]; + krb5_data datain; + krb5_key kc; + + /* Derive the key. */ + datain = make_data(constantdata, K5CLENGTH); + store_32_be(usage, constantdata); + constantdata[4] = (char) 0x99; + ret = krb5int_derive_key(enc, NULL, key, &kc, &datain, DERIVE_RFC3961); + if (ret) + return ret; + + /* Hash the data. */ + ret = krb5int_hmac(ctp->hash, kc, data, num_data, output); + if (ret) + memset(output->data, 0, output->length); + + krb5_k_free_key(NULL, kc); + return ret; +} diff --git a/src/lib/crypto/krb/checksum_etm.c b/src/lib/crypto/krb/checksum_etm.c new file mode 100644 index 000000000000..eaa85b2d507a --- /dev/null +++ b/src/lib/crypto/krb/checksum_etm.c @@ -0,0 +1,65 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/checksum_etm.c - checksum for encrypt-then-mac enctypes */ +/* + * Copyright (C) 2015 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_etm_checksum(const struct krb5_cksumtypes *ctp, krb5_key key, + krb5_keyusage usage, const krb5_crypto_iov *data, + size_t num_data, krb5_data *output) +{ + krb5_error_code ret; + uint8_t label[5]; + krb5_data label_data = make_data(label, 5), kc = empty_data(); + krb5_keyblock kb = { 0 }; + + /* Derive the checksum key. */ + store_32_be(usage, label); + label[4] = 0x99; + label_data = make_data(label, 5); + ret = alloc_data(&kc, ctp->hash->hashsize / 2); + if (ret) + goto cleanup; + ret = krb5int_derive_random(ctp->enc, ctp->hash, key, &kc, &label_data, + DERIVE_SP800_108_HMAC); + if (ret) + goto cleanup; + + /* Compute an HMAC with kc over the data. */ + kb.length = kc.length; + kb.contents = (uint8_t *)kc.data; + ret = krb5int_hmac_keyblock(ctp->hash, &kb, data, num_data, output); + +cleanup: + zapfree(kc.data, kc.length); + return ret; +} diff --git a/src/lib/crypto/krb/checksum_hmac_md5.c b/src/lib/crypto/krb/checksum_hmac_md5.c new file mode 100644 index 000000000000..ec024f396613 --- /dev/null +++ b/src/lib/crypto/krb/checksum_hmac_md5.c @@ -0,0 +1,94 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/checksum_hmac_md5.c */ +/* + * Copyright (C) 2009 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. + */ + +/* + * Microsoft HMAC-MD5 and MD5-HMAC checksums (see RFC 4757): + * HMAC(KS, hash(msusage || input)) + * KS is HMAC(key, "signaturekey\0") for HMAC-MD5, or just the key for + * MD5-HMAC. + */ + +#include "crypto_int.h" + +krb5_error_code krb5int_hmacmd5_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output) +{ + krb5_keyusage ms_usage; + krb5_error_code ret; + krb5_keyblock ks, *keyblock; + krb5_crypto_iov *hash_iov = NULL, iov; + krb5_data ds = empty_data(), hashval = empty_data(); + char t[4]; + + if (key == NULL || key->keyblock.length > ctp->hash->blocksize) + return KRB5_BAD_ENCTYPE; + if (ctp->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) { + /* Compute HMAC(key, "signaturekey\0") to get the signing key ks. */ + ret = alloc_data(&ds, ctp->hash->hashsize); + if (ret != 0) + goto cleanup; + + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data("signaturekey", 13); + ret = krb5int_hmac(ctp->hash, key, &iov, 1, &ds); + if (ret) + goto cleanup; + ks.length = ds.length; + ks.contents = (krb5_octet *) ds.data; + keyblock = &ks; + } else /* For md5-hmac, just use the key. */ + keyblock = &key->keyblock; + + /* Compute the MD5 value of the input. */ + ms_usage = krb5int_arcfour_translate_usage(usage); + store_32_le(ms_usage, t); + hash_iov = k5calloc(num_data + 1, sizeof(krb5_crypto_iov), &ret); + if (hash_iov == NULL) + goto cleanup; + hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + hash_iov[0].data = make_data(t, 4); + memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov)); + ret = alloc_data(&hashval, ctp->hash->hashsize); + if (ret != 0) + goto cleanup; + ret = ctp->hash->hash(hash_iov, num_data + 1, &hashval); + if (ret != 0) + goto cleanup; + + /* Compute HMAC(ks, md5value). */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = hashval; + ret = krb5int_hmac_keyblock(ctp->hash, keyblock, &iov, 1, output); + +cleanup: + zapfree(ds.data, ds.length); + zapfree(hashval.data, hashval.length); + free(hash_iov); + return ret; +} diff --git a/src/lib/crypto/krb/checksum_length.c b/src/lib/crypto/krb/checksum_length.c new file mode 100644 index 000000000000..d4071e1046c7 --- /dev/null +++ b/src/lib/crypto/krb/checksum_length.c @@ -0,0 +1,42 @@ +/* -*- 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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_checksum_length(krb5_context context, krb5_cksumtype cksumtype, + size_t *length) +{ + const struct krb5_cksumtypes *ctp; + + ctp = find_cksumtype(cksumtype); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + *length = ctp->output_size; + return 0; +} diff --git a/src/lib/crypto/krb/checksum_unkeyed.c b/src/lib/crypto/krb/checksum_unkeyed.c new file mode 100644 index 000000000000..ff4f2b46c006 --- /dev/null +++ b/src/lib/crypto/krb/checksum_unkeyed.c @@ -0,0 +1,36 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/checksum_unkeyed.c - Unkeyed checksum handler */ +/* + * Copyright (C) 2009 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 "crypto_int.h" + +krb5_error_code +krb5int_unkeyed_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + return ctp->hash->hash(data, num_data, output); +} diff --git a/src/lib/crypto/krb/cksumtype_to_string.c b/src/lib/crypto/krb/cksumtype_to_string.c new file mode 100644 index 000000000000..758940a18027 --- /dev/null +++ b/src/lib/crypto/krb/cksumtype_to_string.c @@ -0,0 +1,42 @@ +/* -*- 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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_cksumtype_to_string(krb5_cksumtype cksumtype, char *buffer, size_t buflen) +{ + const struct krb5_cksumtypes *ctp; + + ctp = find_cksumtype(cksumtype); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + if (strlcpy(buffer, ctp->out_string, buflen) >= buflen) + return ENOMEM; + return 0; +} diff --git a/src/lib/crypto/krb/cksumtypes.c b/src/lib/crypto/krb/cksumtypes.c new file mode 100644 index 000000000000..85967f9aa0ad --- /dev/null +++ b/src/lib/crypto/krb/cksumtypes.c @@ -0,0 +1,130 @@ +/* -*- 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 "crypto_int.h" + +const struct krb5_cksumtypes krb5int_cksumtypes_list[] = { + { CKSUMTYPE_CRC32, + "crc32", { 0 }, "CRC-32", + NULL, &krb5int_hash_crc32, + krb5int_unkeyed_checksum, NULL, + 4, 4, CKSUM_UNKEYED | CKSUM_NOT_COLL_PROOF }, + + { CKSUMTYPE_RSA_MD4, + "md4", { 0 }, "RSA-MD4", + NULL, &krb5int_hash_md4, + krb5int_unkeyed_checksum, NULL, + 16, 16, CKSUM_UNKEYED }, + + { CKSUMTYPE_RSA_MD4_DES, + "md4-des", { 0 }, "RSA-MD4 with DES cbc mode", + &krb5int_enc_des, &krb5int_hash_md4, + krb5int_confounder_checksum, krb5int_confounder_verify, + 24, 24, 0 }, + + { CKSUMTYPE_DESCBC, + "des-cbc", { 0 }, "DES cbc mode", + &krb5int_enc_des, NULL, + krb5int_cbc_checksum, NULL, + 8, 8, 0 }, + + { CKSUMTYPE_RSA_MD5, + "md5", { 0 }, "RSA-MD5", + NULL, &krb5int_hash_md5, + krb5int_unkeyed_checksum, NULL, + 16, 16, CKSUM_UNKEYED }, + + { CKSUMTYPE_RSA_MD5_DES, + "md5-des", { 0 }, "RSA-MD5 with DES cbc mode", + &krb5int_enc_des, &krb5int_hash_md5, + krb5int_confounder_checksum, krb5int_confounder_verify, + 24, 24, 0 }, + + { CKSUMTYPE_NIST_SHA, + "sha", { 0 }, "NIST-SHA", + NULL, &krb5int_hash_sha1, + krb5int_unkeyed_checksum, NULL, + 20, 20, CKSUM_UNKEYED }, + + { CKSUMTYPE_HMAC_SHA1_DES3, + "hmac-sha1-des3", { "hmac-sha1-des3-kd" }, "HMAC-SHA1 DES3 key", + &krb5int_enc_des3, &krb5int_hash_sha1, + krb5int_dk_checksum, NULL, + 20, 20, 0 }, + + { CKSUMTYPE_HMAC_MD5_ARCFOUR, + "hmac-md5-rc4", { "hmac-md5-enc", "hmac-md5-earcfour" }, + "Microsoft HMAC MD5", + NULL, &krb5int_hash_md5, + krb5int_hmacmd5_checksum, NULL, + 16, 16, 0 }, + + { CKSUMTYPE_HMAC_SHA1_96_AES128, + "hmac-sha1-96-aes128", { 0 }, "HMAC-SHA1 AES128 key", + &krb5int_enc_aes128, &krb5int_hash_sha1, + krb5int_dk_checksum, NULL, + 20, 12, 0 }, + + { CKSUMTYPE_HMAC_SHA1_96_AES256, + "hmac-sha1-96-aes256", { 0 }, "HMAC-SHA1 AES256 key", + &krb5int_enc_aes256, &krb5int_hash_sha1, + krb5int_dk_checksum, NULL, + 20, 12, 0 }, + + { CKSUMTYPE_MD5_HMAC_ARCFOUR, + "md5-hmac-rc4", { 0 }, "Microsoft MD5 HMAC", + &krb5int_enc_arcfour, &krb5int_hash_md5, + krb5int_hmacmd5_checksum, NULL, + 16, 16, 0 }, + + { CKSUMTYPE_CMAC_CAMELLIA128, + "cmac-camellia128", { 0 }, "CMAC Camellia128 key", + &krb5int_enc_camellia128, NULL, + krb5int_dk_cmac_checksum, NULL, + 16, 16, 0 }, + + { CKSUMTYPE_CMAC_CAMELLIA256, + "cmac-camellia256", { 0 }, "CMAC Camellia256 key", + &krb5int_enc_camellia256, NULL, + krb5int_dk_cmac_checksum, NULL, + 16, 16, 0 }, + + { CKSUMTYPE_HMAC_SHA256_128_AES128, + "hmac-sha256-128-aes128", { 0 }, "HMAC-SHA256 AES128 key", + &krb5int_enc_aes128, &krb5int_hash_sha256, + krb5int_etm_checksum, NULL, + 32, 16, 0 }, + + { CKSUMTYPE_HMAC_SHA384_192_AES256, + "hmac-sha384-192-aes256", { 0 }, "HMAC-SHA384 AES256 key", + &krb5int_enc_aes256, &krb5int_hash_sha384, + krb5int_etm_checksum, NULL, + 48, 24, 0 }, +}; + +const size_t krb5int_cksumtypes_length = + sizeof(krb5int_cksumtypes_list) / sizeof(struct krb5_cksumtypes); diff --git a/src/lib/crypto/krb/cmac.c b/src/lib/crypto/krb/cmac.c new file mode 100644 index 000000000000..67ac1a178dce --- /dev/null +++ b/src/lib/crypto/krb/cmac.c @@ -0,0 +1,200 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/cmac.c */ +/* + * Copyright 2010 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 "crypto_int.h" + +#define BLOCK_SIZE 16 + +static unsigned char const_Rb[BLOCK_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 +}; + +static void +xor_128(unsigned char *a, unsigned char *b, unsigned char *out) +{ + int z; + + for (z = 0; z < BLOCK_SIZE / 4; z++) { + unsigned char *aptr = &a[z * 4]; + unsigned char *bptr = &b[z * 4]; + unsigned char *outptr = &out[z * 4]; + + store_32_n(load_32_n(aptr) ^ load_32_n(bptr), outptr); + } +} + +static void +leftshift_onebit(unsigned char *input, unsigned char *output) +{ + int i; + unsigned char overflow = 0; + + for (i = BLOCK_SIZE - 1; i >= 0; i--) { + output[i] = input[i] << 1; + output[i] |= overflow; + overflow = (input[i] & 0x80) ? 1 : 0; + } +} + +/* Generate subkeys K1 and K2 as described in RFC 4493 figure 2.2. */ +static krb5_error_code +generate_subkey(const struct krb5_enc_provider *enc, + krb5_key key, + unsigned char *K1, + unsigned char *K2) +{ + unsigned char L[BLOCK_SIZE]; + unsigned char tmp[BLOCK_SIZE]; + krb5_data d; + krb5_error_code ret; + + /* L := encrypt(K, const_Zero) */ + memset(L, 0, sizeof(L)); + d = make_data(L, BLOCK_SIZE); + ret = encrypt_block(enc, key, &d); + if (ret != 0) + return ret; + + /* K1 := (MSB(L) == 0) ? L << 1 : (L << 1) XOR const_Rb */ + if ((L[0] & 0x80) == 0) { + leftshift_onebit(L, K1); + } else { + leftshift_onebit(L, tmp); + xor_128(tmp, const_Rb, K1); + } + + /* K2 := (MSB(K1) == 0) ? K1 << 1 : (K1 << 1) XOR const_Rb */ + if ((K1[0] & 0x80) == 0) { + leftshift_onebit(K1, K2); + } else { + leftshift_onebit(K1, tmp); + xor_128(tmp, const_Rb, K2); + } + + return 0; +} + +/* Pad out lastb with a 1 bit followed by 0 bits, placing the result in pad. */ +static void +padding(unsigned char *lastb, unsigned char *pad, int length) +{ + int j; + + /* original last block */ + for (j = 0; j < BLOCK_SIZE; j++) { + if (j < length) { + pad[j] = lastb[j]; + } else if (j == length) { + pad[j] = 0x80; + } else { + pad[j] = 0x00; + } + } +} + +/* + * Implementation of CMAC algorithm. When used with AES, this function + * is compatible with RFC 4493 figure 2.3. + */ +krb5_error_code +krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + unsigned char Y[BLOCK_SIZE], M_last[BLOCK_SIZE], padded[BLOCK_SIZE]; + unsigned char K1[BLOCK_SIZE], K2[BLOCK_SIZE]; + unsigned char input[BLOCK_SIZE]; + unsigned int n, i, flag; + krb5_error_code ret; + struct iov_cursor cursor; + size_t length; + krb5_crypto_iov iov[1]; + krb5_data d; + + assert(enc->cbc_mac != NULL); + + if (enc->block_size != BLOCK_SIZE) + return KRB5_BAD_MSIZE; + + length = iov_total_length(data, num_data, TRUE); + + /* Step 1. */ + ret = generate_subkey(enc, key, K1, K2); + if (ret != 0) + return ret; + + /* Step 2. */ + n = (length + BLOCK_SIZE - 1) / BLOCK_SIZE; + + /* Step 3. */ + if (n == 0) { + n = 1; + flag = 0; + } else { + flag = ((length % BLOCK_SIZE) == 0); + } + + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = make_data(input, BLOCK_SIZE); + + /* Step 5 (we'll do step 4 in a bit). */ + memset(Y, 0, BLOCK_SIZE); + d = make_data(Y, BLOCK_SIZE); + + /* Step 6 (all but last block). */ + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, TRUE); + for (i = 0; i < n - 1; i++) { + k5_iov_cursor_get(&cursor, input); + + ret = enc->cbc_mac(key, iov, 1, &d, &d); + if (ret != 0) + return ret; + } + + /* Step 4. */ + k5_iov_cursor_get(&cursor, input); + if (flag) { + /* last block is complete block */ + xor_128(input, K1, M_last); + } else { + padding(input, padded, length % BLOCK_SIZE); + xor_128(padded, K2, M_last); + } + + /* Step 6 (last block). */ + iov[0].data = make_data(M_last, BLOCK_SIZE); + ret = enc->cbc_mac(key, iov, 1, &d, &d); + if (ret != 0) + return ret; + + assert(output->length >= d.length); + + output->length = d.length; + memcpy(output->data, d.data, d.length); + + return 0; +} diff --git a/src/lib/crypto/krb/coll_proof_cksum.c b/src/lib/crypto/krb/coll_proof_cksum.c new file mode 100644 index 000000000000..13cb182aee83 --- /dev/null +++ b/src/lib/crypto/krb/coll_proof_cksum.c @@ -0,0 +1,37 @@ +/* -*- 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 "crypto_int.h" + +krb5_boolean KRB5_CALLCONV +krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype) +{ + const struct krb5_cksumtypes *ctp; + + ctp = find_cksumtype(ctype); + return (ctp != NULL && !(ctp->flags & CKSUM_NOT_COLL_PROOF)); +} diff --git a/src/lib/crypto/krb/combine_keys.c b/src/lib/crypto/krb/combine_keys.c new file mode 100644 index 000000000000..90905c5ae2d8 --- /dev/null +++ b/src/lib/crypto/krb/combine_keys.c @@ -0,0 +1,230 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* Copyright (c) 2002 Naval Research Laboratory (NRL/CCS) */ +/* + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the software, + * derivative works or modified versions, and any portions thereof. + * + * NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND + * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER + * RESULTING FROM THE USE OF THIS SOFTWARE. + */ + +/* + * Key combination function. + * + * If Key1 and Key2 are two keys to be combined, the algorithm to combine + * them is as follows. + * + * Definitions: + * + * k-truncate is defined as truncating to the key size the input. + * + * DR is defined as the generate "random" data from a key + * (defined in crypto draft) + * + * DK is defined as the key derivation function (krb5int_derive_key()) + * + * (note: | means "concatenate") + * + * Combine key algorithm: + * + * R1 = DR(Key1, n-fold(Key2)) [ Output is length of Key1 ] + * R2 = DR(Key2, n-fold(Key1)) [ Output is length of Key2 ] + * + * rnd = n-fold(R1 | R2) [ Note: output size of nfold must be appropriately + * sized for random-to-key function ] + * tkey = random-to-key(rnd) + * Combine-Key(Key1, Key2) = DK(tkey, CombineConstant) + * + * CombineConstant is defined as the byte string: + * + * { 0x63 0x6f 0x6d 0x62 0x69 0x6e 0x65 }, which corresponds to the + * ASCII encoding of the string "combine" + */ + +#include "crypto_int.h" + +static krb5_error_code dr(const struct krb5_enc_provider *enc, + const krb5_keyblock *inkey, unsigned char *outdata, + const krb5_data *in_constant); + +/* + * We only support this combine_keys algorithm for des and 3des keys. + * Everything else should use the PRF defined in the crypto framework. + * We don't implement that yet. + */ + +static krb5_boolean +enctype_ok(krb5_enctype e) +{ + switch (e) { + case ENCTYPE_DES_CBC_CRC: + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES3_CBC_SHA1: + return TRUE; + default: + return FALSE; + } +} + +krb5_error_code +krb5int_c_combine_keys(krb5_context context, krb5_keyblock *key1, + krb5_keyblock *key2, krb5_keyblock *outkey) +{ + unsigned char *r1 = NULL, *r2 = NULL, *combined = NULL, *rnd = NULL; + unsigned char *output = NULL; + size_t keybytes, keylength; + const struct krb5_enc_provider *enc; + krb5_data input, randbits; + krb5_keyblock tkeyblock; + krb5_key tkey = NULL; + krb5_error_code ret; + const struct krb5_keytypes *ktp; + krb5_boolean myalloc = FALSE; + + if (!enctype_ok(key1->enctype) || !enctype_ok(key2->enctype)) + return KRB5_CRYPTO_INTERNAL; + + if (key1->length != key2->length || key1->enctype != key2->enctype) + return KRB5_CRYPTO_INTERNAL; + + /* Find our encryption algorithm. */ + ktp = find_enctype(key1->enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + enc = ktp->enc; + + keybytes = enc->keybytes; + keylength = enc->keylength; + + /* Allocate and set up buffers. */ + r1 = k5alloc(keybytes, &ret); + if (ret) + goto cleanup; + r2 = k5alloc(keybytes, &ret); + if (ret) + goto cleanup; + rnd = k5alloc(keybytes, &ret); + if (ret) + goto cleanup; + combined = k5calloc(2, keybytes, &ret); + if (ret) + goto cleanup; + output = k5alloc(keylength, &ret); + if (ret) + goto cleanup; + + /* + * Get R1 and R2 (by running the input keys through the DR algorithm. + * Note this is most of derive-key, but not all. + */ + + input.length = key2->length; + input.data = (char *) key2->contents; + ret = dr(enc, key1, r1, &input); + if (ret) + goto cleanup; + + input.length = key1->length; + input.data = (char *) key1->contents; + ret = dr(enc, key2, r2, &input); + if (ret) + goto cleanup; + + /* + * Concatenate the two keys together, and then run them through + * n-fold to reduce them to a length appropriate for the random-to-key + * operation. Note here that krb5int_nfold() takes sizes in bits, hence + * the multiply by 8. + */ + + memcpy(combined, r1, keybytes); + memcpy(combined + keybytes, r2, keybytes); + + krb5int_nfold((keybytes * 2) * 8, combined, keybytes * 8, rnd); + + /* + * Run the "random" bits through random-to-key to produce a encryption + * key. + */ + + randbits.length = keybytes; + randbits.data = (char *) rnd; + tkeyblock.length = keylength; + tkeyblock.contents = output; + tkeyblock.enctype = key1->enctype; + + ret = (*ktp->rand2key)(&randbits, &tkeyblock); + if (ret) + goto cleanup; + + ret = krb5_k_create_key(NULL, &tkeyblock, &tkey); + if (ret) + goto cleanup; + + /* + * Run through derive-key one more time to produce the final key. + * Note that the input to derive-key is the ASCII string "combine". + */ + + input.length = 7; + input.data = "combine"; + + /* + * Just FYI: _if_ we have space here in the key, then simply use it + * without modification. But if the key is blank (no allocated storage) + * then allocate some memory for it. This allows programs to use one of + * the existing keys as the output key, _or_ pass in a blank keyblock + * for us to allocate. It's easier for us to allocate it since we already + * know the crypto library internals + */ + + if (outkey->length == 0 || outkey->contents == NULL) { + outkey->contents = k5alloc(keylength, &ret); + if (ret) + goto cleanup; + outkey->length = keylength; + outkey->enctype = key1->enctype; + myalloc = TRUE; + } + + ret = krb5int_derive_keyblock(enc, NULL, tkey, outkey, &input, + DERIVE_RFC3961); + if (ret) { + if (myalloc) { + free(outkey->contents); + outkey->contents = NULL; + } + goto cleanup; + } + +cleanup: + zapfree(r1, keybytes); + zapfree(r2, keybytes); + zapfree(rnd, keybytes); + zapfree(combined, keybytes * 2); + zapfree(output, keylength); + krb5_k_free_key(NULL, tkey); + return ret; +} + +/* Our DR function, a simple wrapper around krb5int_derive_random(). */ +static krb5_error_code +dr(const struct krb5_enc_provider *enc, const krb5_keyblock *inkey, + unsigned char *out, const krb5_data *in_constant) +{ + krb5_data outdata = make_data(out, enc->keybytes); + krb5_key key = NULL; + krb5_error_code ret; + + ret = krb5_k_create_key(NULL, inkey, &key); + if (ret != 0) + return ret; + ret = krb5int_derive_random(enc, NULL, key, &outdata, in_constant, + DERIVE_RFC3961); + krb5_k_free_key(NULL, key); + return ret; +} diff --git a/src/lib/crypto/krb/crc32.c b/src/lib/crypto/krb/crc32.c new file mode 100644 index 000000000000..d3b1b7a134d8 --- /dev/null +++ b/src/lib/crypto/krb/crc32.c @@ -0,0 +1,165 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/crc32.c */ +/* + * Copyright 1990, 2002 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. + */ +/* + * Copyright (C) 1986 Gary S. Brown. You may use this program, or + * code or tables extracted from it, as desired without restriction. + */ + +/* + * + * CRC-32/AUTODIN-II routines + */ + +#include "crypto_int.h" + +/* First, the polynomial itself and its table of feedback terms. The */ +/* polynomial is */ +/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ +/* Note that we take it "backwards" and put the highest-order term in */ +/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ +/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ +/* the MSB being 1. */ + +/* Note that the usual hardware shift register implementation, which */ +/* is what we're using (we're merely optimizing it by doing eight-bit */ +/* chunks at a time) shifts bits into the lowest-order term. In our */ +/* implementation, that means shifting towards the right. Why do we */ +/* do it this way? Because the calculated CRC must be transmitted in */ +/* order from highest-order term to lowest-order term. UARTs transmit */ +/* characters in order from LSB to MSB. By storing the CRC this way, */ +/* we hand it to the UART in the order low-byte to high-byte; the UART */ +/* sends each low-bit to hight-bit; and the result is transmission bit */ +/* by bit from highest- to lowest-order term without requiring any bit */ +/* shuffling on our part. Reception works similarly. */ + +/* The feedback terms table consists of 256, 32-bit entries. Notes: */ +/* */ +/* 1. The table can be generated at runtime if desired; code to do so */ +/* is shown later. It might not be obvious, but the feedback */ +/* terms simply represent the results of eight shift/xor opera- */ +/* tions for all combinations of data and CRC register values. */ +/* */ +/* 2. The CRC accumulation logic is the same for all CRC polynomials, */ +/* be they sixteen or thirty-two bits wide. You simply choose the */ +/* appropriate table. Alternatively, because the table can be */ +/* generated at runtime, you can start by generating the table for */ +/* the polynomial in question and use exactly the same "updcrc", */ +/* if your application needn't simultaneously handle two CRC */ +/* polynomials. (Note, however, that XMODEM is strange.) */ +/* */ +/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */ +/* of course, 32-bit entries work OK if the high 16 bits are zero. */ +/* */ +/* 4. The values must be right-shifted by eight bits by the "updcrc" */ +/* logic; the shift must be unsigned (bring in zeroes). On some */ +/* hardware you could probably optimize the shift in assembler by */ +/* using byte-swap instructions. */ + +static u_long const crc_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +void +mit_crc32(krb5_pointer in, size_t in_length, unsigned long *cksum) +{ + register u_char *data; + register u_long c = *cksum; + register int idx; + size_t i; + + data = (u_char *)in; + for (i = 0; i < in_length; i++) { + idx = (int) (data[i] ^ c); + idx &= 0xff; + c >>= 8; + c ^= crc_table[idx]; + } + + *cksum = c; +} diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h new file mode 100644 index 000000000000..d75b49c693f0 --- /dev/null +++ b/src/lib/crypto/krb/crypto_int.h @@ -0,0 +1,668 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/crypto_int.h - Master libk5crypto internal header */ +/* + * Copyright (C) 2011 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. + */ + +/* This header is the entry point for libk5crypto sources, and also documents + * requirements for crypto modules and PRNG modules. */ + +#ifndef CRYPTO_INT_H +#define CRYPTO_INT_H + +#include <k5-int.h> + +/* Enc providers and hash providers specify well-known ciphers and hashes to be + * implemented by the crypto module. */ + +struct krb5_enc_provider { + /* keybytes is the input size to make_key; + keylength is the output size */ + size_t block_size, keybytes, keylength; + + krb5_error_code (*encrypt)(krb5_key key, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data); + + krb5_error_code (*decrypt)(krb5_key key, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data); + + /* May be NULL if the cipher is not used for a cbc-mac checksum. */ + krb5_error_code (*cbc_mac)(krb5_key key, const krb5_crypto_iov *data, + size_t num_data, const krb5_data *ivec, + krb5_data *output); + + krb5_error_code (*init_state)(const krb5_keyblock *key, + krb5_keyusage keyusage, + krb5_data *out_state); + void (*free_state)(krb5_data *state); + + /* May be NULL if there is no key-derived data cached. */ + void (*key_cleanup)(krb5_key key); +}; + +struct krb5_hash_provider { + char hash_name[8]; + size_t hashsize, blocksize; + + krb5_error_code (*hash)(const krb5_crypto_iov *data, size_t num_data, + krb5_data *output); +}; + +/*** RFC 3961 enctypes table ***/ + +#define MAX_ETYPE_ALIASES 2 + +struct krb5_keytypes; + +typedef unsigned int (*crypto_length_func)(const struct krb5_keytypes *ktp, + krb5_cryptotype type); + +typedef krb5_error_code (*crypt_func)(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage keyusage, + const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); + +typedef krb5_error_code (*str2key_func)(const struct krb5_keytypes *ktp, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *parm, + krb5_keyblock *key); + +typedef krb5_error_code (*rand2key_func)(const krb5_data *randombits, + krb5_keyblock *key); + +typedef krb5_error_code (*prf_func)(const struct krb5_keytypes *ktp, + krb5_key key, + const krb5_data *in, krb5_data *out); + +struct krb5_keytypes { + krb5_enctype etype; + char *name; + char *aliases[MAX_ETYPE_ALIASES]; + char *out_string; + const struct krb5_enc_provider *enc; + const struct krb5_hash_provider *hash; + size_t prf_length; + crypto_length_func crypto_length; + crypt_func encrypt; + crypt_func decrypt; + str2key_func str2key; + rand2key_func rand2key; + prf_func prf; + krb5_cksumtype required_ctype; + krb5_flags flags; +}; + +#define ETYPE_WEAK 1 + +extern const struct krb5_keytypes krb5int_enctypes_list[]; +extern const int krb5int_enctypes_length; + +/*** RFC 3961 checksum types table ***/ + +struct krb5_cksumtypes; + +/* + * Compute a checksum over the header, data, padding, and sign-only fields of + * the iov array data (of size num_data). The output buffer will already be + * allocated with ctp->compute_size bytes available; the handler just needs to + * fill in the contents. If ctp->enc is not NULL, the handler can assume that + * key is a valid-length key of an enctype which uses that enc provider. + */ +typedef krb5_error_code (*checksum_func)(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output); + +/* + * Verify a checksum over the header, data, padding, and sign-only fields of + * the iov array data (of size num_data), and store the boolean result in + * *valid. The handler can assume that hash has length ctp->output_size. If + * ctp->enc is not NULL, the handler can assume that key a valid-length key of + * an enctype which uses that enc provider. + */ +typedef krb5_error_code (*verify_func)(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + const krb5_data *input, + krb5_boolean *valid); + +struct krb5_cksumtypes { + krb5_cksumtype ctype; + char *name; + char *aliases[2]; + char *out_string; + const struct krb5_enc_provider *enc; + const struct krb5_hash_provider *hash; + checksum_func checksum; + verify_func verify; /* NULL means recompute checksum and compare */ + unsigned int compute_size; /* Allocation size for checksum computation */ + unsigned int output_size; /* Possibly truncated output size */ + krb5_flags flags; +}; + +#define CKSUM_UNKEYED 0x0001 +#define CKSUM_NOT_COLL_PROOF 0x0002 + +extern const struct krb5_cksumtypes krb5int_cksumtypes_list[]; +extern const size_t krb5int_cksumtypes_length; + +/*** Prototypes for enctype table functions ***/ + +/* Length */ +unsigned int krb5int_old_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); +unsigned int krb5int_raw_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); +unsigned int krb5int_arcfour_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); +unsigned int krb5int_dk_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); +unsigned int krb5int_aes_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); +unsigned int krb5int_camellia_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); +unsigned int krb5int_aes2_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); + +/* Encrypt */ +krb5_error_code krb5int_old_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_raw_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_arcfour_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_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_cmac_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_etm_encrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); + +/* Decrypt */ +krb5_error_code krb5int_old_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_raw_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_arcfour_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_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_dk_cmac_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_etm_decrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); + +/* String to key */ +krb5_error_code krb5int_des_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key); +krb5_error_code krb5int_arcfour_string_to_key(const struct krb5_keytypes *ktp, + 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_keytypes *enc, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key); +krb5_error_code 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_camellia_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_aes2_string_to_key(const struct krb5_keytypes *enc, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key); + +/* Random to key */ +krb5_error_code k5_rand2key_direct(const krb5_data *randombits, + krb5_keyblock *keyblock); +krb5_error_code k5_rand2key_des(const krb5_data *randombits, + krb5_keyblock *keyblock); +krb5_error_code k5_rand2key_des3(const krb5_data *randombits, + krb5_keyblock *keyblock); + +/* Pseudo-random function */ +krb5_error_code krb5int_des_prf(const struct krb5_keytypes *ktp, + krb5_key key, const krb5_data *in, + krb5_data *out); +krb5_error_code krb5int_arcfour_prf(const struct krb5_keytypes *ktp, + krb5_key key, const krb5_data *in, + krb5_data *out); +krb5_error_code krb5int_dk_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out); +krb5_error_code krb5int_dk_cmac_prf(const struct krb5_keytypes *ktp, + krb5_key key, const krb5_data *in, + krb5_data *out); +krb5_error_code krb5int_aes2_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out); + +/*** Prototypes for cksumtype handler functions ***/ + +krb5_error_code krb5int_unkeyed_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output); +krb5_error_code krb5int_cbc_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output); +krb5_error_code krb5int_hmacmd5_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output); +krb5_error_code krb5int_dk_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, krb5_data *output); +krb5_error_code krb5int_dk_cmac_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, krb5_data *output); +krb5_error_code krb5int_confounder_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output); +krb5_error_code krb5int_confounder_verify(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + const krb5_data *input, + krb5_boolean *valid); +krb5_error_code krb5int_etm_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, krb5_data *output); + +/*** Key derivation functions ***/ + +enum deriv_alg { + DERIVE_RFC3961, /* RFC 3961 section 5.1 */ + DERIVE_SP800_108_CMAC, /* NIST SP 800-108 with CMAC as PRF */ + DERIVE_SP800_108_HMAC /* NIST SP 800-108 with HMAC as PRF */ +}; + +krb5_error_code krb5int_derive_keyblock(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_keyblock *outkey, + const krb5_data *in_constant, + enum deriv_alg alg); +krb5_error_code krb5int_derive_key(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_key *outkey, + const krb5_data *in_constant, + enum deriv_alg alg); +krb5_error_code krb5int_derive_random(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_data *outrnd, + const krb5_data *in_constant, + enum deriv_alg alg); +krb5_error_code +k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_data *outrnd, + const krb5_data *label, const krb5_data *context); + +/*** Miscellaneous prototypes ***/ + +/* nfold algorithm from RFC 3961 */ +void krb5int_nfold(unsigned int inbits, const unsigned char *in, + unsigned int outbits, unsigned char *out); + +/* Compute a CMAC checksum over data. */ +krb5_error_code krb5int_cmac_checksum(const struct krb5_enc_provider *enc, + krb5_key key, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output); + +/* Compute a CRC-32 checksum. c is in-out to allow chaining; init to 0. */ +#define CRC32_CKSUM_LENGTH 4 +void mit_crc32(krb5_pointer in, size_t in_length, unsigned long *c); + +/* Translate an RFC 3961 key usage to a Microsoft RC4 usage. */ +krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage); + +/* Ensure library initialization has occurred. */ +int krb5int_crypto_init(void); + +/* DES default state initialization handler (used by module enc providers). */ +krb5_error_code krb5int_des_init_state(const krb5_keyblock *key, + krb5_keyusage keyusage, + krb5_data *state_out); + +/* Default state cleanup handler (used by module enc providers). */ +void krb5int_default_free_state(krb5_data *state); + +/*** Input/output vector processing declarations **/ + +#define ENCRYPT_CONF_IOV(_iov) ((_iov)->flags == KRB5_CRYPTO_TYPE_HEADER) + +#define ENCRYPT_DATA_IOV(_iov) ((_iov)->flags == KRB5_CRYPTO_TYPE_DATA || \ + (_iov)->flags == KRB5_CRYPTO_TYPE_PADDING) + +#define ENCRYPT_IOV(_iov) (ENCRYPT_CONF_IOV(_iov) || ENCRYPT_DATA_IOV(_iov)) + +#define SIGN_IOV(_iov) (ENCRYPT_IOV(_iov) || \ + (_iov)->flags == KRB5_CRYPTO_TYPE_SIGN_ONLY ) + +struct iov_cursor { + const krb5_crypto_iov *iov; /* iov array we are iterating over */ + size_t iov_count; /* size of iov array */ + size_t block_size; /* size of blocks we will be obtaining */ + krb5_boolean signing; /* should we process SIGN_ONLY blocks */ + size_t in_iov; /* read index into iov array */ + size_t in_pos; /* read index into iov contents */ + size_t out_iov; /* write index into iov array */ + size_t out_pos; /* write index into iov contents */ +}; + +krb5_crypto_iov *krb5int_c_locate_iov(krb5_crypto_iov *data, size_t num_data, + krb5_cryptotype type); + +krb5_error_code krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp, + krb5_key key, + krb5_keyusage keyusage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data); + +unsigned int krb5int_c_padding_length(const struct krb5_keytypes *ktp, + size_t data_length); + +void k5_iov_cursor_init(struct iov_cursor *cursor, const krb5_crypto_iov *iov, + size_t count, size_t block_size, krb5_boolean signing); + +krb5_boolean k5_iov_cursor_get(struct iov_cursor *cursor, + unsigned char *block); + +void k5_iov_cursor_put(struct iov_cursor *cursor, unsigned char *block); + +/*** Crypto module declarations ***/ + +/* Modules must implement the k5_sha256() function prototyped in k5-int.h. */ + +/* Modules must implement the following enc_providers and hash_providers: */ +extern const struct krb5_enc_provider krb5int_enc_des; +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; +extern const struct krb5_enc_provider krb5int_enc_camellia128; +extern const struct krb5_enc_provider krb5int_enc_camellia256; + +extern const struct krb5_hash_provider krb5int_hash_crc32; +extern const struct krb5_hash_provider krb5int_hash_md4; +extern const struct krb5_hash_provider krb5int_hash_md5; +extern const struct krb5_hash_provider krb5int_hash_sha1; +extern const struct krb5_hash_provider krb5int_hash_sha256; +extern const struct krb5_hash_provider krb5int_hash_sha384; + +/* Modules must implement the following functions. */ + +/* Set the parity bits to the correct values in keybits. */ +void k5_des_fixup_key_parity(unsigned char *keybits); + +/* Return true if keybits is a weak or semi-weak DES key. */ +krb5_boolean k5_des_is_weak_key(unsigned char *keybits); + +/* Compute an HMAC using the provided hash function, key, and data, storing the + * result into output (caller-allocated). */ +krb5_error_code krb5int_hmac(const struct krb5_hash_provider *hash, + krb5_key key, const krb5_crypto_iov *data, + size_t num_data, krb5_data *output); + +/* As above, using a keyblock as the key input. */ +krb5_error_code krb5int_hmac_keyblock(const struct krb5_hash_provider *hash, + const krb5_keyblock *keyblock, + const krb5_crypto_iov *data, + size_t num_data, krb5_data *output); + +/* + * Compute the PBKDF2 (see RFC 2898) of password and salt, with the specified + * count, using HMAC with the specified hash as the pseudo-random function, + * storing the result into out (caller-allocated). + */ +krb5_error_code krb5int_pbkdf2_hmac(const struct krb5_hash_provider *hash, + const krb5_data *out, unsigned long count, + const krb5_data *password, + const krb5_data *salt); + +/* The following are used by test programs and are just handler functions from + * the AES and Camellia enc providers. */ +krb5_error_code krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); +krb5_error_code krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); +krb5_error_code krb5int_camellia_cbc_mac(krb5_key key, + const krb5_crypto_iov *data, + size_t num_data, const krb5_data *iv, + krb5_data *output); + +/* These can be used to safely set up and tear down module global state. */ +int krb5int_crypto_impl_init(void); +void krb5int_crypto_impl_cleanup(void); + +/* + * Modules must provide a crypto_mod.h header at the top level. To work with + * the default PRNG module (prng_fortuna.c), crypto_mod.h must #define or + * prototype the following symbols: + * + * aes_ctx - Stack-allocatable type for an AES-128 or AES-256 key schedule + * krb5int_aes_enc_key(key, keybits, ctxptr) -- initialize a key schedule + * krb5int_aes_enc_blk(in, out, ctxptr) -- encrypt a block + * SHA256_CTX - Stack-allocatable type for a SHA-256 hash state + * k5_sha256_init(ctxptr) - Initialize a hash state + * k5_sha256_update(ctxptr, data, size) -- Hash some data + * k5_sha256_final(ctxptr, out) -- Finalize a state, writing hash into out + * + * These functions must never fail on valid inputs, and contexts must remain + * valid across forks. If the module cannot meet those constraints, then it + * should provide its own PRNG module and the build system should ensure that + * it is used. + * + * The function symbols named above are also in the library export list (so + * they can be used by the t_fortuna.c test code), so even if the module + * defines them away or doesn't work with Fortuna, the module must provide + * stubs; see stubs.c in the openssl module for examples. + */ + +#include <crypto_mod.h> + +/*** PRNG module declarations ***/ + +/* + * PRNG modules must implement the following APIs from krb5.h: + * krb5_c_random_add_entropy + * krb5_c_random_make_octets + * krb5_c_random_os_entropy + * + * PRNG modules should implement these functions. They are called from the + * crypto library init and cleanup functions, and can be used to setup and tear + * down static state without thread safety concerns. + */ +int k5_prng_init(void); +void k5_prng_cleanup(void); + +/* Used by PRNG modules to gather OS entropy. Returns true on success. */ +krb5_boolean k5_get_os_entropy(unsigned char *buf, size_t len, int strong); + +/*** Inline helper functions ***/ + +/* Find an enctype by number in the enctypes table. */ +static inline const struct krb5_keytypes * +find_enctype(krb5_enctype enctype) +{ + int i; + + for (i = 0; i < krb5int_enctypes_length; i++) { + if (krb5int_enctypes_list[i].etype == enctype) + break; + } + + if (i == krb5int_enctypes_length) + return NULL; + return &krb5int_enctypes_list[i]; +} + +/* Find a checksum type by number in the cksumtypes table. */ +static inline const struct krb5_cksumtypes * +find_cksumtype(krb5_cksumtype ctype) +{ + size_t i; + + for (i = 0; i < krb5int_cksumtypes_length; i++) { + if (krb5int_cksumtypes_list[i].ctype == ctype) + break; + } + + if (i == krb5int_cksumtypes_length) + return NULL; + return &krb5int_cksumtypes_list[i]; +} + +/* Verify that a key is appropriate for a checksum type. */ +static inline krb5_error_code +verify_key(const struct krb5_cksumtypes *ctp, krb5_key key) +{ + const struct krb5_keytypes *ktp; + + ktp = key ? find_enctype(key->keyblock.enctype) : NULL; + if (ctp->enc != NULL && (!ktp || ktp->enc != ctp->enc)) + return KRB5_BAD_ENCTYPE; + if (key && (!ktp || key->keyblock.length != ktp->enc->keylength)) + return KRB5_BAD_KEYSIZE; + return 0; +} + +/* Encrypt one block of plaintext in place, for block ciphers. */ +static inline krb5_error_code +encrypt_block(const struct krb5_enc_provider *enc, krb5_key key, + krb5_data *block) +{ + krb5_crypto_iov iov; + + /* Verify that this is a block cipher and block is the right length. */ + if (block->length != enc->block_size || enc->block_size == 1) + return EINVAL; + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *block; + if (enc->cbc_mac != NULL) /* One-block cbc-mac with no ivec. */ + return enc->cbc_mac(key, &iov, 1, NULL, block); + else /* Assume cbc-mode encrypt. */ + return enc->encrypt(key, 0, &iov, 1); +} + +/* Return the total length of the to-be-signed or to-be-encrypted buffers in an + * iov chain. */ +static inline size_t +iov_total_length(const krb5_crypto_iov *data, size_t num_data, + krb5_boolean signing) +{ + size_t i, total = 0; + + for (i = 0; i < num_data; i++) { + if (signing ? SIGN_IOV(&data[i]) : ENCRYPT_IOV(&data[i])) + total += data[i].data.length; + } + return total; +} + +/* + * Return the number of contiguous blocks available within the current input + * IOV of the cursor c, so that the caller can do in-place encryption. + * Do not call if c might be exhausted. + */ +static inline size_t +iov_cursor_contig_blocks(struct iov_cursor *c) +{ + return (c->iov[c->in_iov].data.length - c->in_pos) / c->block_size; +} + +/* Return the current input pointer within the cursor c. Do not call if c + * might be exhausted. */ +static inline unsigned char * +iov_cursor_ptr(struct iov_cursor *c) +{ + return (unsigned char *)&c->iov[c->in_iov].data.data[c->in_pos]; +} + +/* + * Advance the input and output pointers of c by nblocks blocks. nblocks must + * not be greater than the return value of iov_cursor_contig_blocks, and the + * input and output positions must be identical. + */ +static inline void +iov_cursor_advance(struct iov_cursor *c, size_t nblocks) +{ + c->in_pos += nblocks * c->block_size; + c->out_pos += nblocks * c->block_size; +} + +#endif /* CRYPTO_INT_H */ diff --git a/src/lib/crypto/krb/crypto_length.c b/src/lib/crypto/krb/crypto_length.c new file mode 100644 index 000000000000..a621423a1e21 --- /dev/null +++ b/src/lib/crypto/krb/crypto_length.c @@ -0,0 +1,125 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/crypto_length.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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_crypto_length(krb5_context context, krb5_enctype enctype, + krb5_cryptotype type, unsigned int *size) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + switch (type) { + case KRB5_CRYPTO_TYPE_EMPTY: + case KRB5_CRYPTO_TYPE_SIGN_ONLY: + *size = 0; + break; + case KRB5_CRYPTO_TYPE_DATA: + *size = (unsigned int)~0; /* match Heimdal */ + break; + case KRB5_CRYPTO_TYPE_HEADER: + case KRB5_CRYPTO_TYPE_PADDING: + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + *size = ktp->crypto_length(ktp, type); + break; + default: + return EINVAL; + } + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_padding_length(krb5_context context, krb5_enctype enctype, + size_t data_length, unsigned int *pad_length) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + *pad_length = krb5int_c_padding_length(ktp, data_length); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_crypto_length_iov(krb5_context context, krb5_enctype enctype, + krb5_crypto_iov *data, size_t num_data) +{ + size_t i; + const struct krb5_keytypes *ktp; + unsigned int data_length = 0, pad_length; + krb5_crypto_iov *padding = NULL; + + /* + * XXX need to rejig internal interface so we can accurately + * report variable header lengths. + */ + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + for (i = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + switch (iov->flags) { + case KRB5_CRYPTO_TYPE_DATA: + data_length += iov->data.length; + break; + case KRB5_CRYPTO_TYPE_PADDING: + if (padding != NULL) + return EINVAL; + + padding = iov; + break; + case KRB5_CRYPTO_TYPE_HEADER: + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + iov->data.length = ktp->crypto_length(ktp, iov->flags); + break; + case KRB5_CRYPTO_TYPE_EMPTY: + case KRB5_CRYPTO_TYPE_SIGN_ONLY: + default: + break; + } + } + + pad_length = krb5int_c_padding_length(ktp, data_length); + if (pad_length != 0 && padding == NULL) + return EINVAL; + + if (padding != NULL) + padding->data.length = pad_length; + + return 0; +} diff --git a/src/lib/crypto/krb/crypto_libinit.c b/src/lib/crypto/krb/crypto_libinit.c new file mode 100644 index 000000000000..3b62ff5de0eb --- /dev/null +++ b/src/lib/crypto/krb/crypto_libinit.c @@ -0,0 +1,35 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include "crypto_int.h" + +MAKE_INIT_FUNCTION(cryptoint_initialize_library); +MAKE_FINI_FUNCTION(cryptoint_cleanup_library); + +/* + * Initialize the crypto library. + */ + +int cryptoint_initialize_library (void) +{ + int err; + err = k5_prng_init(); + if (err) + return err; + return krb5int_crypto_impl_init(); +} + +int krb5int_crypto_init(void) +{ + return CALL_INIT_FUNCTION(cryptoint_initialize_library); +} + +/* + * Clean up the crypto library state + */ + +void cryptoint_cleanup_library (void) +{ + if (!INITIALIZER_RAN(cryptoint_initialize_library)) + return; + k5_prng_cleanup(); + krb5int_crypto_impl_cleanup(); +} diff --git a/src/lib/crypto/krb/decrypt.c b/src/lib/crypto/krb/decrypt.c new file mode 100644 index 000000000000..496d262e9e66 --- /dev/null +++ b/src/lib/crypto/krb/decrypt.c @@ -0,0 +1,101 @@ +/* -*- 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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_decrypt(krb5_context context, krb5_key key, + krb5_keyusage usage, const krb5_data *cipher_state, + const krb5_enc_data *input, krb5_data *output) +{ + const struct krb5_keytypes *ktp; + krb5_crypto_iov iov[4]; + krb5_error_code ret; + unsigned int header_len, trailer_len, plain_len; + char *scratch = NULL; + + ktp = find_enctype(key->keyblock.enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + if (input->enctype != ENCTYPE_UNKNOWN && ktp->etype != input->enctype) + return KRB5_BAD_ENCTYPE; + + /* Verify the input and output lengths. */ + header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + if (input->ciphertext.length < header_len + trailer_len) + return KRB5_BAD_MSIZE; + plain_len = input->ciphertext.length - header_len - trailer_len; + if (output->length < plain_len) + return KRB5_BAD_MSIZE; + + scratch = k5alloc(header_len + trailer_len, &ret); + if (scratch == NULL) + return ret; + + iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; + iov[0].data = make_data(scratch, header_len); + memcpy(iov[0].data.data, input->ciphertext.data, header_len); + + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = make_data(output->data, plain_len); + memcpy(iov[1].data.data, input->ciphertext.data + header_len, plain_len); + + /* Use empty padding since tokens don't indicate the padding length. */ + iov[2].flags = KRB5_CRYPTO_TYPE_PADDING; + iov[2].data = empty_data(); + + iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER; + iov[3].data = make_data(scratch + header_len, trailer_len); + memcpy(iov[3].data.data, input->ciphertext.data + header_len + plain_len, + trailer_len); + + ret = ktp->decrypt(ktp, key, usage, cipher_state, iov, 4); + if (ret != 0) + zap(output->data, plain_len); + else + output->length = plain_len; + zapfree(scratch, header_len + trailer_len); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_decrypt(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *cipher_state, + const krb5_enc_data *input, krb5_data *output) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_decrypt(context, key, usage, cipher_state, input, output); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/decrypt_iov.c b/src/lib/crypto/krb/decrypt_iov.c new file mode 100644 index 000000000000..8d43e8ff6168 --- /dev/null +++ b/src/lib/crypto/krb/decrypt_iov.c @@ -0,0 +1,64 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/decrypt_iov.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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_decrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, + const krb5_data *cipher_state, krb5_crypto_iov *data, + size_t num_data) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(key->keyblock.enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + if (krb5int_c_locate_iov(data, num_data, + KRB5_CRYPTO_TYPE_STREAM) != NULL) { + return krb5int_c_iov_decrypt_stream(ktp, key, usage, cipher_state, + data, num_data); + } + + return ktp->decrypt(ktp, key, usage, cipher_state, data, num_data); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_decrypt_iov(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_decrypt_iov(context, key, usage, cipher_state, data, + num_data); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/default_state.c b/src/lib/crypto/krb/default_state.c new file mode 100644 index 000000000000..c7bfe323f799 --- /dev/null +++ b/src/lib/crypto/krb/default_state.c @@ -0,0 +1,54 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2001, 2014 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. + * + * Section 6 (Encryption) of the Kerberos revisions document defines + * cipher states to be used to chain encryptions and decryptions + * together. Examples of cipher states include initialization vectors + * for CBC encription. Most Kerberos encryption systems can share + * code for initializing and freeing cipher states. This file + * contains that default code. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_des_init_state(const krb5_keyblock *key, krb5_keyusage usage, + krb5_data *state_out) +{ + if (alloc_data(state_out, 8)) + return ENOMEM; + + /* des-cbc-crc uses the key as the initial ivec. */ + if (key->enctype == ENCTYPE_DES_CBC_CRC) + memcpy(state_out->data, key->contents, state_out->length); + + return 0; +} + +void +krb5int_default_free_state(krb5_data *state) +{ + free(state->data); + *state = empty_data(); +} diff --git a/src/lib/crypto/krb/deps b/src/lib/crypto/krb/deps new file mode 100644 index 000000000000..2a7f9b0effd3 --- /dev/null +++ b/src/lib/crypto/krb/deps @@ -0,0 +1,783 @@ +# +# Generated makefile dependencies follow. +# +aead.so aead.po $(OUTPRE)aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + aead.c crypto_int.h +block_size.so block_size.po $(OUTPRE)block_size.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h block_size.c crypto_int.h +cf2.so cf2.po $(OUTPRE)cf2.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cf2.c crypto_int.h +checksum_cbc.so checksum_cbc.po $(OUTPRE)checksum_cbc.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h checksum_cbc.c \ + crypto_int.h +checksum_confounder.so checksum_confounder.po $(OUTPRE)checksum_confounder.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h checksum_confounder.c \ + crypto_int.h +checksum_dk_cmac.so checksum_dk_cmac.po $(OUTPRE)checksum_dk_cmac.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h checksum_dk_cmac.c \ + crypto_int.h +checksum_dk_hmac.so checksum_dk_hmac.po $(OUTPRE)checksum_dk_hmac.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h checksum_dk_hmac.c \ + crypto_int.h +checksum_etm.so checksum_etm.po $(OUTPRE)checksum_etm.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h checksum_etm.c \ + crypto_int.h +checksum_hmac_md5.so checksum_hmac_md5.po $(OUTPRE)checksum_hmac_md5.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h checksum_hmac_md5.c \ + crypto_int.h +checksum_unkeyed.so checksum_unkeyed.po $(OUTPRE)checksum_unkeyed.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h checksum_unkeyed.c \ + crypto_int.h +checksum_length.so checksum_length.po $(OUTPRE)checksum_length.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h checksum_length.c \ + crypto_int.h +cksumtype_to_string.so cksumtype_to_string.po $(OUTPRE)cksumtype_to_string.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cksumtype_to_string.c \ + crypto_int.h +cksumtypes.so cksumtypes.po $(OUTPRE)cksumtypes.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cksumtypes.c crypto_int.h +cmac.so cmac.po $(OUTPRE)cmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cmac.c crypto_int.h +coll_proof_cksum.so coll_proof_cksum.po $(OUTPRE)coll_proof_cksum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h coll_proof_cksum.c \ + crypto_int.h +combine_keys.so combine_keys.po $(OUTPRE)combine_keys.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h combine_keys.c \ + crypto_int.h +crc32.so crc32.po $(OUTPRE)crc32.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crc32.c crypto_int.h +crypto_length.so crypto_length.po $(OUTPRE)crypto_length.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h crypto_length.c +crypto_libinit.so crypto_libinit.po $(OUTPRE)crypto_libinit.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h crypto_libinit.c +default_state.so default_state.po $(OUTPRE)default_state.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h default_state.c +decrypt.so decrypt.po $(OUTPRE)decrypt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h decrypt.c +decrypt_iov.so decrypt_iov.po $(OUTPRE)decrypt_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h decrypt_iov.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) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h derive.c +encrypt.so encrypt.po $(OUTPRE)encrypt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h encrypt.c +encrypt_iov.so encrypt_iov.po $(OUTPRE)encrypt_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h encrypt_iov.c +encrypt_length.so encrypt_length.po $(OUTPRE)encrypt_length.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h encrypt_length.c +enctype_util.so enctype_util.po $(OUTPRE)enctype_util.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h enctype_util.c +enc_dk_cmac.so enc_dk_cmac.po $(OUTPRE)enc_dk_cmac.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h enc_dk_cmac.c +enc_dk_hmac.so enc_dk_hmac.po $(OUTPRE)enc_dk_hmac.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h enc_dk_hmac.c +enc_etm.so enc_etm.po $(OUTPRE)enc_etm.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h enc_etm.c +enc_old.so enc_old.po $(OUTPRE)enc_old.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h enc_old.c +enc_raw.so enc_raw.po $(OUTPRE)enc_raw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h enc_raw.c +enc_rc4.so enc_rc4.po $(OUTPRE)enc_rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h enc_rc4.c +etypes.so etypes.po $(OUTPRE)etypes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h etypes.c +key.so key.po $(OUTPRE)key.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h key.c +keyblocks.so keyblocks.po $(OUTPRE)keyblocks.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h keyblocks.c +keyed_cksum.so keyed_cksum.po $(OUTPRE)keyed_cksum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h keyed_cksum.c +keyed_checksum_types.so keyed_checksum_types.po $(OUTPRE)keyed_checksum_types.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h keyed_checksum_types.c +keylengths.so keylengths.po $(OUTPRE)keylengths.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h keylengths.c +make_checksum.so make_checksum.po $(OUTPRE)make_checksum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h make_checksum.c +make_checksum_iov.so make_checksum_iov.po $(OUTPRE)make_checksum_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h make_checksum_iov.c +make_random_key.so make_random_key.po $(OUTPRE)make_random_key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h make_random_key.c +mandatory_sumtype.so mandatory_sumtype.po $(OUTPRE)mandatory_sumtype.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h mandatory_sumtype.c +nfold.so nfold.po $(OUTPRE)nfold.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h nfold.c +old_api_glue.so old_api_glue.po $(OUTPRE)old_api_glue.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h old_api_glue.c +prf.so prf.po $(OUTPRE)prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h prf.c +prf_aes2.so prf_aes2.po $(OUTPRE)prf_aes2.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h prf_aes2.c +prf_cmac.so prf_cmac.po $(OUTPRE)prf_cmac.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h prf_cmac.c +prf_des.so prf_des.po $(OUTPRE)prf_des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h prf_des.c +prf_dk.so prf_dk.po $(OUTPRE)prf_dk.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h prf_dk.c +prf_rc4.so prf_rc4.po $(OUTPRE)prf_rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h prf_rc4.c +prng.so prng.po $(OUTPRE)prng.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h prng.c +prng_fortuna.so prng_fortuna.po $(OUTPRE)prng_fortuna.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h prng_fortuna.c +random_to_key.so random_to_key.po $(OUTPRE)random_to_key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h random_to_key.c +s2k_des.so s2k_des.po $(OUTPRE)s2k_des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h s2k_des.c +s2k_pbkdf2.so s2k_pbkdf2.po $(OUTPRE)s2k_pbkdf2.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h s2k_pbkdf2.c +s2k_rc4.so s2k_rc4.po $(OUTPRE)s2k_rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/k5-utf8.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h s2k_rc4.c +state.so state.po $(OUTPRE)state.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h \ + $(srcdir)/../builtin/crypto_mod.h $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h state.c +string_to_cksumtype.so string_to_cksumtype.po $(OUTPRE)string_to_cksumtype.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h string_to_cksumtype.c +string_to_key.so string_to_key.po $(OUTPRE)string_to_key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h string_to_key.c +t_fortuna.so t_fortuna.po $(OUTPRE)t_fortuna.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h prng_fortuna.c \ + t_fortuna.c +valid_cksumtype.so valid_cksumtype.po $(OUTPRE)valid_cksumtype.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h valid_cksumtype.c +verify_checksum.so verify_checksum.po $(OUTPRE)verify_checksum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h verify_checksum.c +verify_checksum_iov.so verify_checksum_iov.po $(OUTPRE)verify_checksum_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../builtin/aes/aes.h $(srcdir)/../builtin/crypto_mod.h \ + $(srcdir)/../builtin/sha2/sha2.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/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h verify_checksum_iov.c diff --git a/src/lib/crypto/krb/derive.c b/src/lib/crypto/krb/derive.c new file mode 100644 index 000000000000..6707a7308259 --- /dev/null +++ b/src/lib/crypto/krb/derive.c @@ -0,0 +1,354 @@ +/* -*- 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 "crypto_int.h" + +static krb5_key +find_cached_dkey(struct derived_key *list, const krb5_data *constant) +{ + for (; list; list = list->next) { + if (data_eq(list->constant, *constant)) { + krb5_k_reference_key(NULL, list->dkey); + return list->dkey; + } + } + return NULL; +} + +static krb5_error_code +add_cached_dkey(krb5_key key, const krb5_data *constant, + const krb5_keyblock *dkeyblock, krb5_key *cached_dkey) +{ + krb5_key dkey; + krb5_error_code ret; + struct derived_key *dkent = NULL; + char *data = NULL; + + /* Allocate fields for the new entry. */ + dkent = malloc(sizeof(*dkent)); + if (dkent == NULL) + goto cleanup; + data = k5memdup(constant->data, constant->length, &ret); + if (data == NULL) + goto cleanup; + ret = krb5_k_create_key(NULL, dkeyblock, &dkey); + if (ret != 0) + goto cleanup; + + /* Add the new entry to the list. */ + dkent->dkey = dkey; + dkent->constant.data = data; + dkent->constant.length = constant->length; + dkent->next = key->derived; + key->derived = dkent; + + /* Return a "copy" of the cached key. */ + krb5_k_reference_key(NULL, dkey); + *cached_dkey = dkey; + return 0; + +cleanup: + free(dkent); + free(data); + return ENOMEM; +} + +static krb5_error_code +derive_random_rfc3961(const struct krb5_enc_provider *enc, + krb5_key inkey, krb5_data *outrnd, + const krb5_data *in_constant) +{ + size_t blocksize, keybytes, n; + krb5_error_code ret; + krb5_data block = empty_data(); + + blocksize = enc->block_size; + keybytes = enc->keybytes; + + if (blocksize == 1) + return KRB5_BAD_ENCTYPE; + if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes) + return KRB5_CRYPTO_INTERNAL; + + /* Allocate encryption data buffer. */ + ret = alloc_data(&block, blocksize); + if (ret) + return ret; + + /* Initialize the input block. */ + if (in_constant->length == blocksize) { + memcpy(block.data, in_constant->data, blocksize); + } else { + krb5int_nfold(in_constant->length * 8, + (unsigned char *) in_constant->data, + blocksize * 8, (unsigned char *) block.data); + } + + /* Loop encrypting the blocks until enough key bytes are generated. */ + n = 0; + while (n < keybytes) { + ret = encrypt_block(enc, inkey, &block); + if (ret) + goto cleanup; + + if ((keybytes - n) <= blocksize) { + memcpy(outrnd->data + n, block.data, (keybytes - n)); + break; + } + + memcpy(outrnd->data + n, block.data, blocksize); + n += blocksize; + } + +cleanup: + zapfree(block.data, blocksize); + return ret; +} + +/* + * NIST SP800-108 KDF in feedback mode (section 5.2). + * Parameters: + * - CMAC (with enc as the enc provider) is the PRF. + * - A block counter of four bytes is used. + * - Label is the key derivation constant. + * - Context is empty. + * - Four bytes are used to encode the output length in the PRF input. + */ +static krb5_error_code +derive_random_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc, + krb5_key inkey, krb5_data *outrnd, + const krb5_data *in_constant) +{ + size_t blocksize, keybytes, n; + krb5_crypto_iov iov[6]; + krb5_error_code ret; + krb5_data prf; + unsigned int i; + unsigned char ibuf[4], Lbuf[4]; + + blocksize = enc->block_size; + keybytes = enc->keybytes; + + if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes) + return KRB5_CRYPTO_INTERNAL; + + /* Allocate encryption data buffer. */ + ret = alloc_data(&prf, blocksize); + if (ret) + return ret; + + /* K(i-1): the previous block of PRF output, initially all-zeros. */ + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = prf; + /* [i]2: four-byte big-endian binary string giving the block counter */ + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = make_data(ibuf, sizeof(ibuf)); + /* Label: the fixed derived-key input */ + iov[2].flags = KRB5_CRYPTO_TYPE_DATA; + iov[2].data = *in_constant; + /* 0x00: separator byte */ + iov[3].flags = KRB5_CRYPTO_TYPE_DATA; + iov[3].data = make_data("", 1); + /* Context: (unused) */ + iov[4].flags = KRB5_CRYPTO_TYPE_DATA; + iov[4].data = empty_data(); + /* [L]2: four-byte big-endian binary string giving the output length */ + iov[5].flags = KRB5_CRYPTO_TYPE_DATA; + iov[5].data = make_data(Lbuf, sizeof(Lbuf)); + store_32_be(outrnd->length * 8, Lbuf); + + for (i = 1, n = 0; n < keybytes; i++) { + /* Update the block counter. */ + store_32_be(i, ibuf); + + /* Compute a CMAC checksum, storing the result into K(i-1). */ + ret = krb5int_cmac_checksum(enc, inkey, iov, 6, &prf); + if (ret) + goto cleanup; + + /* Copy the result into the appropriate part of the output buffer. */ + if (keybytes - n <= blocksize) { + memcpy(outrnd->data + n, prf.data, keybytes - n); + break; + } + memcpy(outrnd->data + n, prf.data, blocksize); + n += blocksize; + } + +cleanup: + zapfree(prf.data, blocksize); + return ret; +} + +/* + * NIST SP800-108 KDF in counter mode (section 5.1). + * Parameters: + * - HMAC (with hash as the hash provider) is the PRF. + * - A block counter of four bytes is used. + * - Four bytes are used to encode the output length in the PRF input. + * + * There are no uses requiring more than a single PRF invocation. + */ +krb5_error_code +k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_data *outrnd, + const krb5_data *label, const krb5_data *context) +{ + krb5_crypto_iov iov[5]; + krb5_error_code ret; + krb5_data prf; + unsigned char ibuf[4], lbuf[4]; + + if (hash == NULL || outrnd->length > hash->hashsize) + return KRB5_CRYPTO_INTERNAL; + + /* Allocate encryption data buffer. */ + ret = alloc_data(&prf, hash->hashsize); + if (ret) + return ret; + + /* [i]2: four-byte big-endian binary string giving the block counter (1) */ + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = make_data(ibuf, sizeof(ibuf)); + store_32_be(1, ibuf); + /* Label */ + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = *label; + /* 0x00: separator byte */ + iov[2].flags = KRB5_CRYPTO_TYPE_DATA; + iov[2].data = make_data("", 1); + /* Context */ + iov[3].flags = KRB5_CRYPTO_TYPE_DATA; + iov[3].data = *context; + /* [L]2: four-byte big-endian binary string giving the output length */ + iov[4].flags = KRB5_CRYPTO_TYPE_DATA; + iov[4].data = make_data(lbuf, sizeof(lbuf)); + store_32_be(outrnd->length * 8, lbuf); + + ret = krb5int_hmac(hash, inkey, iov, 5, &prf); + if (!ret) + memcpy(outrnd->data, prf.data, outrnd->length); + zapfree(prf.data, prf.length); + return ret; +} + +krb5_error_code +krb5int_derive_random(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_data *outrnd, + const krb5_data *in_constant, enum deriv_alg alg) +{ + krb5_data empty = empty_data(); + + switch (alg) { + case DERIVE_RFC3961: + return derive_random_rfc3961(enc, inkey, outrnd, in_constant); + case DERIVE_SP800_108_CMAC: + return derive_random_sp800_108_feedback_cmac(enc, inkey, outrnd, + in_constant); + case DERIVE_SP800_108_HMAC: + return k5_sp800_108_counter_hmac(hash, inkey, outrnd, in_constant, + &empty); + default: + return EINVAL; + } +} + +/* + * 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, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_keyblock *outkey, + const krb5_data *in_constant, enum deriv_alg alg) +{ + krb5_error_code ret; + krb5_data rawkey = empty_data(); + + /* Allocate a buffer for the raw key bytes. */ + ret = alloc_data(&rawkey, enc->keybytes); + if (ret) + goto cleanup; + + /* Derive pseudo-random data for the key bytes. */ + ret = krb5int_derive_random(enc, hash, inkey, &rawkey, in_constant, alg); + if (ret) + goto cleanup; + + /* Postprocess the key. */ + ret = krb5_c_random_to_key(NULL, inkey->keyblock.enctype, &rawkey, outkey); + +cleanup: + zapfree(rawkey.data, enc->keybytes); + return ret; +} + +krb5_error_code +krb5int_derive_key(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_key *outkey, + const krb5_data *in_constant, enum deriv_alg alg) +{ + krb5_keyblock keyblock; + krb5_error_code ret; + krb5_key dkey; + + *outkey = NULL; + + /* Check for a cached result. */ + dkey = find_cached_dkey(inkey->derived, in_constant); + if (dkey != NULL) { + *outkey = dkey; + return 0; + } + + /* Derive into a temporary keyblock. */ + keyblock.length = enc->keylength; + keyblock.contents = malloc(keyblock.length); + keyblock.enctype = inkey->keyblock.enctype; + if (keyblock.contents == NULL) + return ENOMEM; + ret = krb5int_derive_keyblock(enc, hash, inkey, &keyblock, in_constant, + alg); + if (ret) + goto cleanup; + + /* Cache the derived key. */ + ret = add_cached_dkey(inkey, in_constant, &keyblock, &dkey); + if (ret != 0) + goto cleanup; + + *outkey = dkey; + +cleanup: + zapfree(keyblock.contents, keyblock.length); + return ret; +} diff --git a/src/lib/crypto/krb/enc_dk_cmac.c b/src/lib/crypto/krb/enc_dk_cmac.c new file mode 100644 index 000000000000..b65b9b70eb1c --- /dev/null +++ b/src/lib/crypto/krb/enc_dk_cmac.c @@ -0,0 +1,182 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/enc_dk_cmac.c - Derived-key enctype functions using CMAC */ +/* + * Copyright 2008, 2009, 2010 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 "crypto_int.h" + +#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ + +/* AEAD */ + +unsigned int +krb5int_camellia_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 ktp->enc->block_size; + default: + assert(0 && "bad type passed to krb5int_camellia_crypto_length"); + return 0; + } +} + +/* Derive encryption and integrity keys for CMAC-using enctypes. */ +static krb5_error_code +derive_keys(const struct krb5_enc_provider *enc, krb5_key key, + krb5_keyusage usage, krb5_key *ke_out, krb5_key *ki_out) +{ + krb5_error_code ret; + unsigned char buf[K5CLENGTH]; + krb5_data constant = make_data(buf, K5CLENGTH); + krb5_key ke, ki; + + *ke_out = *ki_out = NULL; + + /* Derive the encryption key. */ + store_32_be(usage, buf); + buf[4] = 0xAA; + ret = krb5int_derive_key(enc, NULL, key, &ke, &constant, + DERIVE_SP800_108_CMAC); + if (ret != 0) + return ret; + + /* Derive the integrity key. */ + buf[4] = 0x55; + ret = krb5int_derive_key(enc, NULL, key, &ki, &constant, + DERIVE_SP800_108_CMAC); + if (ret != 0) { + krb5_k_free_key(NULL, ke); + return ret; + } + + *ke_out = ke; + *ki_out = ki; + return 0; +} + +krb5_error_code +krb5int_dk_cmac_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; + krb5_error_code ret; + krb5_crypto_iov *header, *trailer, *padding; + krb5_key ke = NULL, ki = NULL; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + /* Validate header and trailer lengths, and zero out padding length. */ + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length < enc->block_size) + return KRB5_BAD_MSIZE; + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length < enc->block_size) + return KRB5_BAD_MSIZE; + padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING); + if (padding != NULL) + padding->data.length = 0; + + /* Derive the encryption and integrity keys. */ + ret = derive_keys(enc, key, usage, &ke, &ki); + if (ret != 0) + goto cleanup; + + /* Generate confounder. */ + header->data.length = enc->block_size; + ret = krb5_c_random_make_octets(NULL, &header->data); + if (ret != 0) + goto cleanup; + + /* Checksum the plaintext. */ + ret = krb5int_cmac_checksum(enc, ki, data, num_data, &trailer->data); + if (ret != 0) + goto cleanup; + + /* Encrypt the plaintext (header | data | padding) */ + ret = enc->encrypt(ke, ivec, data, num_data); + if (ret != 0) + goto cleanup; + +cleanup: + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); + return ret; +} + +krb5_error_code +krb5int_dk_cmac_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; + krb5_error_code ret; + krb5_crypto_iov *header, *trailer; + krb5_data cksum = empty_data(); + krb5_key ke = NULL, ki = NULL; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + /* Validate header and trailer lengths. */ + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length != enc->block_size) + return KRB5_BAD_MSIZE; + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length != enc->block_size) + return KRB5_BAD_MSIZE; + + /* Derive the encryption and integrity keys. */ + ret = derive_keys(enc, key, usage, &ke, &ki); + if (ret != 0) + goto cleanup; + + /* Decrypt the plaintext (header | data | padding). */ + ret = enc->decrypt(ke, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + /* Verify the hash. */ + ret = alloc_data(&cksum, enc->block_size); + if (ret != 0) + goto cleanup; + ret = krb5int_cmac_checksum(enc, ki, data, num_data, &cksum); + if (ret != 0) + goto cleanup; + if (k5_bcmp(cksum.data, trailer->data.data, enc->block_size) != 0) + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + +cleanup: + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); + zapfree(cksum.data, cksum.length); + return ret; +} diff --git a/src/lib/crypto/krb/enc_dk_hmac.c b/src/lib/crypto/krb/enc_dk_hmac.c new file mode 100644 index 000000000000..713044c67d69 --- /dev/null +++ b/src/lib/crypto/krb/enc_dk_hmac.c @@ -0,0 +1,269 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/enc_dk_hmac.c */ +/* + * Copyright 2008, 2009 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 "crypto_int.h" + +#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ + +/* AEAD */ + +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: + return ktp->enc->block_size; + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + return ktp->hash->hashsize; + default: + assert(0 && "invalid cryptotype passed to krb5int_dk_crypto_length"); + 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; + } +} + +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, hmacsize, plainlen = 0, padsize = 0; + unsigned char *cksum = NULL; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + 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]; + + if (iov->flags == KRB5_CRYPTO_TYPE_DATA) + plainlen += iov->data.length; + } + + /* Validate header and trailer lengths. */ + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length < enc->block_size) + return KRB5_BAD_MSIZE; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length < hmacsize) + return KRB5_BAD_MSIZE; + + 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; + } + + cksum = k5alloc(hash->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] = 0xAA; + + ret = krb5int_derive_key(enc, NULL, key, &ke, &d1, DERIVE_RFC3961); + if (ret != 0) + goto cleanup; + + d1.data[4] = 0x55; + + ret = krb5int_derive_key(enc, NULL, key, &ki, &d1, DERIVE_RFC3961); + if (ret != 0) + goto cleanup; + + /* Generate confounder. */ + + header->data.length = enc->block_size; + + ret = krb5_c_random_make_octets(/* XXX */ NULL, &header->data); + if (ret != 0) + goto cleanup; + + /* Hash the plaintext. */ + d2.length = hash->hashsize; + d2.data = (char *)cksum; + + ret = krb5int_hmac(hash, ki, data, num_data, &d2); + if (ret != 0) + goto cleanup; + + /* Encrypt the plaintext (header | data | padding) */ + ret = enc->encrypt(ke, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + /* Possibly truncate the hash */ + assert(hmacsize <= d2.length); + + memcpy(trailer->data.data, cksum, hmacsize); + trailer->data.length = hmacsize; + +cleanup: + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); + free(cksum); + return ret; +} + +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; /* enc block size, not confounder len */ + unsigned int hmacsize, cipherlen = 0; + unsigned char *cksum = NULL; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + 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. */ + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_DATA_IOV(iov)) + cipherlen += iov->data.length; + } + if (cipherlen % blocksize != 0) + return KRB5_BAD_MSIZE; + } + + /* Validate header and trailer lengths */ + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length != enc->block_size) + return KRB5_BAD_MSIZE; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length != hmacsize) + return KRB5_BAD_MSIZE; + + cksum = k5alloc(hash->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] = 0xAA; + + ret = krb5int_derive_key(enc, NULL, key, &ke, &d1, DERIVE_RFC3961); + if (ret != 0) + goto cleanup; + + d1.data[4] = 0x55; + + ret = krb5int_derive_key(enc, NULL, key, &ki, &d1, DERIVE_RFC3961); + if (ret != 0) + goto cleanup; + + /* Decrypt the plaintext (header | data | padding). */ + ret = enc->decrypt(ke, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + /* Verify the hash. */ + d1.length = hash->hashsize; /* non-truncated length */ + d1.data = (char *)cksum; + + ret = krb5int_hmac(hash, ki, data, num_data, &d1); + if (ret != 0) + goto cleanup; + + /* Compare only the possibly truncated length. */ + if (k5_bcmp(cksum, trailer->data.data, hmacsize) != 0) { + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + +cleanup: + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); + free(cksum); + return ret; +} diff --git a/src/lib/crypto/krb/enc_etm.c b/src/lib/crypto/krb/enc_etm.c new file mode 100644 index 000000000000..3135dd5bb8d7 --- /dev/null +++ b/src/lib/crypto/krb/enc_etm.c @@ -0,0 +1,257 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/enc_etm.c - encrypt-then-mac construction for aes-sha2 */ +/* + * Copyright (C) 2015 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "crypto_int.h" + +unsigned int +krb5int_aes2_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 ktp->hash->hashsize / 2; + default: + assert(0 && "invalid cryptotype passed to krb5int_aes2_crypto_length"); + return 0; + } +} + +/* Derive encryption and integrity keys for CMAC-using enctypes. */ +static krb5_error_code +derive_keys(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, krb5_key *ke_out, krb5_data *ki_out) +{ + krb5_error_code ret; + uint8_t label[5]; + krb5_data label_data = make_data(label, 5), ki = empty_data(); + krb5_key ke = NULL; + + *ke_out = NULL; + *ki_out = empty_data(); + + /* Derive the encryption key. */ + store_32_be(usage, label); + label[4] = 0xAA; + ret = krb5int_derive_key(ktp->enc, ktp->hash, key, &ke, &label_data, + DERIVE_SP800_108_HMAC); + if (ret) + goto cleanup; + + /* Derive the integrity key. */ + label[4] = 0x55; + ret = alloc_data(&ki, ktp->hash->hashsize / 2); + if (ret) + goto cleanup; + ret = krb5int_derive_random(NULL, ktp->hash, key, &ki, &label_data, + DERIVE_SP800_108_HMAC); + if (ret) + goto cleanup; + + *ke_out = ke; + ke = NULL; + *ki_out = ki; + ki = empty_data(); + +cleanup: + krb5_k_free_key(NULL, ke); + zapfree(ki.data, ki.length); + return ret; +} + +/* Compute an HMAC checksum over the cipher state and data. Allocate enough + * space in *out for the checksum. */ +static krb5_error_code +hmac_ivec_data(const struct krb5_keytypes *ktp, const krb5_data *ki, + const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data, + krb5_data *out) +{ + krb5_error_code ret; + krb5_data zeroivec = empty_data(); + krb5_crypto_iov *iovs = NULL; + krb5_keyblock kb = { 0 }; + + if (ivec == NULL) { + ret = ktp->enc->init_state(NULL, 0, &zeroivec); + if (ret) + goto cleanup; + ivec = &zeroivec; + } + + /* Make a copy of data with an extra iov at the beginning for the ivec. */ + iovs = k5calloc(num_data + 1, sizeof(*iovs), &ret); + if (iovs == NULL) + goto cleanup; + iovs[0].flags = KRB5_CRYPTO_TYPE_DATA; + iovs[0].data = *ivec; + memcpy(iovs + 1, data, num_data * sizeof(*iovs)); + + ret = alloc_data(out, ktp->hash->hashsize); + if (ret) + goto cleanup; + kb.length = ki->length; + kb.contents = (uint8_t *)ki->data; + ret = krb5int_hmac_keyblock(ktp->hash, &kb, iovs, num_data + 1, out); + +cleanup: + if (zeroivec.data != NULL) + ktp->enc->free_state(&zeroivec); + free(iovs); + return ret; +} + +krb5_error_code +krb5int_etm_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; + krb5_error_code ret; + krb5_data ivcopy = empty_data(), cksum = empty_data(); + krb5_crypto_iov *header, *trailer, *padding; + krb5_key ke = NULL; + krb5_data ki = empty_data(); + unsigned int trailer_len; + + /* E(Confounder | Plaintext) | Checksum(IV | ciphertext) */ + + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + + /* Validate header and trailer lengths, and zero out padding length. */ + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length < enc->block_size) + return KRB5_BAD_MSIZE; + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length < trailer_len) + return KRB5_BAD_MSIZE; + padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING); + if (padding != NULL) + padding->data.length = 0; + + if (ivec != NULL) { + ret = alloc_data(&ivcopy, ivec->length); + if (ret) + goto cleanup; + memcpy(ivcopy.data, ivec->data, ivec->length); + } + + /* Derive the encryption and integrity keys. */ + ret = derive_keys(ktp, key, usage, &ke, &ki); + if (ret) + goto cleanup; + + /* Generate confounder. */ + header->data.length = enc->block_size; + ret = krb5_c_random_make_octets(NULL, &header->data); + if (ret) + goto cleanup; + + /* Encrypt the plaintext (header | data). */ + ret = enc->encrypt(ke, (ivec == NULL) ? NULL : &ivcopy, data, num_data); + if (ret) + goto cleanup; + + /* HMAC the IV, confounder, and ciphertext with sign-only data. */ + ret = hmac_ivec_data(ktp, &ki, ivec, data, num_data, &cksum); + if (ret) + goto cleanup; + + /* Truncate the HMAC checksum to the trailer length. */ + assert(trailer_len <= cksum.length); + memcpy(trailer->data.data, cksum.data, trailer_len); + trailer->data.length = trailer_len; + + /* Copy out the updated ivec if desired. */ + if (ivec != NULL) + memcpy(ivec->data, ivcopy.data, ivcopy.length); + +cleanup: + krb5_k_free_key(NULL, ke); + zapfree(ki.data, ki.length); + free(cksum.data); + zapfree(ivcopy.data, ivcopy.length); + return ret; +} + +krb5_error_code +krb5int_etm_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; + krb5_error_code ret; + krb5_data cksum = empty_data(); + krb5_crypto_iov *header, *trailer; + krb5_key ke = NULL; + krb5_data ki = empty_data(); + unsigned int trailer_len; + + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + + /* Validate header and trailer lengths. */ + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length != enc->block_size) + return KRB5_BAD_MSIZE; + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length != trailer_len) + return KRB5_BAD_MSIZE; + + /* Derive the encryption and integrity keys. */ + ret = derive_keys(ktp, key, usage, &ke, &ki); + if (ret) + goto cleanup; + + /* HMAC the IV, confounder, and ciphertext with sign-only data. */ + ret = hmac_ivec_data(ktp, &ki, ivec, data, num_data, &cksum); + if (ret) + goto cleanup; + + /* Compare only the possibly truncated length. */ + assert(trailer_len <= cksum.length); + if (k5_bcmp(cksum.data, trailer->data.data, trailer_len) != 0) { + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + + /* Decrypt the ciphertext (header | data | padding). */ + ret = enc->decrypt(ke, ivec, data, num_data); + +cleanup: + krb5_k_free_key(NULL, ke); + zapfree(ki.data, ki.length); + zapfree(cksum.data, cksum.length); + return ret; +} diff --git a/src/lib/crypto/krb/enc_old.c b/src/lib/crypto/krb/enc_old.c new file mode 100644 index 000000000000..1b02a59157e4 --- /dev/null +++ b/src/lib/crypto/krb/enc_old.c @@ -0,0 +1,181 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/enc_old.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 "crypto_int.h" + +unsigned int +krb5int_old_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + return ktp->enc->block_size + ktp->hash->hashsize; + case KRB5_CRYPTO_TYPE_PADDING: + return ktp->enc->block_size; + case KRB5_CRYPTO_TYPE_TRAILER: + return 0; + case KRB5_CRYPTO_TYPE_CHECKSUM: + return ktp->hash->hashsize; + default: + assert(0 && "invalid cryptotype passed to krb5int_old_crypto_length"); + return 0; + } +} + +krb5_error_code +krb5int_old_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; + 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 = hash->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); + if (ret != 0) + goto cleanup; + memcpy(crcivec.data, key->keyblock.contents, key->keyblock.length); + ivec = &crcivec; + } + + ret = enc->encrypt(key, ivec, data, num_data); + if (ret != 0) + goto cleanup; + +cleanup: + zapfree(crcivec.data, crcivec.length); + return ret; +} + +krb5_error_code +krb5int_old_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; + krb5_crypto_iov *header, *trailer; + krb5_data checksum, crcivec = empty_data(); + char *saved_checksum = NULL; + + /* Check that the input data is correctly padded. */ + if (iov_total_length(data, num_data, FALSE) % 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(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 = k5memdup(checksum.data, checksum.length, &ret); + if (saved_checksum == NULL) + goto cleanup; + 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 = hash->hash(data, num_data, &checksum); + if (k5_bcmp(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; +} diff --git a/src/lib/crypto/krb/enc_raw.c b/src/lib/crypto/krb/enc_raw.c new file mode 100644 index 000000000000..554d5c4d648d --- /dev/null +++ b/src/lib/crypto/krb/enc_raw.c @@ -0,0 +1,109 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/enc_raw.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 "crypto_int.h" + +unsigned int +krb5int_raw_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_PADDING: + return ktp->enc->block_size; + default: + return 0; + } +} + +krb5_error_code +krb5int_raw_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_crypto_iov *padding; + size_t i; + unsigned int blocksize, plainlen = 0, padsize = 0; + + blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING); + + 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; + } + + return ktp->enc->encrypt(key, ivec, data, num_data); +} + +krb5_error_code +krb5int_raw_decrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + size_t i; + unsigned int blocksize = 0; /* enc block size, not confounder len */ + unsigned int cipherlen = 0; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING); + + 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 (ktp->enc->block_size != 0 && cipherlen < ktp->enc->block_size) + return KRB5_BAD_MSIZE; + } else { + /* Check that the input data is correctly padded */ + if (cipherlen % blocksize != 0) + return KRB5_BAD_MSIZE; + } + + return ktp->enc->decrypt(key, ivec, data, num_data); +} diff --git a/src/lib/crypto/krb/enc_rc4.c b/src/lib/crypto/krb/enc_rc4.c new file mode 100644 index 000000000000..aac8508b137c --- /dev/null +++ b/src/lib/crypto/krb/enc_rc4.c @@ -0,0 +1,347 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + + ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95). + This cipher is widely believed and has been tested to be equivalent + with the RC4 cipher from RSA Data Security, Inc. (RC4 is a trademark + of RSA Data Security) + +*/ +#include "crypto_int.h" + +#define CONFOUNDERLENGTH 8 + +const char l40[] = "fortybits"; + +krb5_keyusage +krb5int_arcfour_translate_usage(krb5_keyusage usage) +{ + switch (usage) { + case 1: return 1; /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, */ + case 2: return 2; /* ticket from kdc */ + case 3: return 8; /* as-rep encrypted part */ + case 4: return 4; /* tgs-req authz data */ + case 5: return 5; /* tgs-req authz data in subkey */ + case 6: return 6; /* tgs-req authenticator cksum */ + case 7: return 7; /* tgs-req authenticator */ + case 8: return 8; + case 9: return 9; /* tgs-rep encrypted with subkey */ + case 10: return 10; /* ap-rep authentication cksum (never used by MS) */ + case 11: return 11; /* app-req authenticator */ + case 12: return 12; /* app-rep encrypted part */ + case 23: return 13; /* sign wrap token*/ + default: return usage; + } +} + +/* Derive a usage key from a session key and krb5 usage constant. */ +static krb5_error_code +usage_key(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *session_keyblock, krb5_keyusage usage, + krb5_keyblock *out) +{ + char salt_buf[14]; + unsigned int salt_len; + krb5_data out_data = make_data(out->contents, out->length); + krb5_crypto_iov iov; + krb5_keyusage ms_usage; + + /* Generate the salt. */ + ms_usage = krb5int_arcfour_translate_usage(usage); + if (session_keyblock->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + memcpy(salt_buf, l40, 10); + store_32_le(ms_usage, salt_buf + 10); + salt_len = 14; + } else { + store_32_le(ms_usage, salt_buf); + salt_len = 4; + } + + /* Compute HMAC(key, salt) to produce the usage key. */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data(salt_buf, salt_len); + return krb5int_hmac_keyblock(hash, session_keyblock, &iov, 1, &out_data); +} + +/* Derive an encryption key from a usage key and (typically) checksum. */ +static krb5_error_code +enc_key(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *usage_keyblock, const krb5_data *checksum, + krb5_keyblock *out) +{ + krb5_keyblock *trunc_keyblock = NULL; + krb5_data out_data = make_data(out->contents, out->length); + krb5_crypto_iov iov; + krb5_error_code ret; + + /* Copy usage_keyblock to trunc_keyblock and truncate if exportable. */ + ret = krb5int_c_copy_keyblock(NULL, usage_keyblock, &trunc_keyblock); + if (ret != 0) + return ret; + if (trunc_keyblock->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + memset(trunc_keyblock->contents + 7, 0xab, 9); + + /* Compute HMAC(trunc_key, checksum) to produce the encryption key. */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *checksum; + ret = krb5int_hmac_keyblock(hash, trunc_keyblock, &iov, 1, &out_data); + krb5int_c_free_keyblock(NULL, trunc_keyblock); + return ret; +} + +unsigned int +krb5int_arcfour_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + return ktp->hash->hashsize + CONFOUNDERLENGTH; + case KRB5_CRYPTO_TYPE_PADDING: + case KRB5_CRYPTO_TYPE_TRAILER: + return 0; + case KRB5_CRYPTO_TYPE_CHECKSUM: + return ktp->hash->hashsize; + default: + assert(0 && + "invalid cryptotype passed to krb5int_arcfour_crypto_length"); + return 0; + } +} + +/* Encrypt or decrypt using a keyblock. */ +static krb5_error_code +keyblock_crypt(const struct krb5_enc_provider *enc, krb5_keyblock *keyblock, + const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) +{ + krb5_error_code ret; + krb5_key key; + + ret = krb5_k_create_key(NULL, keyblock, &key); + if (ret != 0) + return ret; + /* Works for encryption or decryption since arcfour is a stream cipher. */ + ret = enc->encrypt(key, ivec, data, num_data); + krb5_k_free_key(NULL, key); + return ret; +} + +krb5_error_code +krb5int_arcfour_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; + krb5_crypto_iov *header, *trailer; + krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL; + krb5_data checksum, confounder, header_data; + size_t i; + + /* + * Caller must have provided space for the header, padding + * and trailer; per RFC 4757 we will arrange it as: + * + * Checksum | E(Confounder | Plaintext) + */ + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length < hash->hashsize + CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + + header_data = header->data; + + /* Trailer may be absent. */ + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL) + trailer->data.length = 0; + + /* Ensure that there is no padding. */ + for (i = 0; i < num_data; i++) { + if (data[i].flags == KRB5_CRYPTO_TYPE_PADDING) + data[i].data.length = 0; + } + + ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, + &usage_keyblock); + if (ret != 0) + goto cleanup; + ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, + &enc_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive a usage key from the session key and usage. */ + ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock); + if (ret != 0) + goto cleanup; + + /* Generate a confounder in the header block, after the checksum. */ + header->data.length = hash->hashsize + CONFOUNDERLENGTH; + confounder = make_data(header->data.data + hash->hashsize, + CONFOUNDERLENGTH); + ret = krb5_c_random_make_octets(0, &confounder); + if (ret != 0) + goto cleanup; + checksum = make_data(header->data.data, hash->hashsize); + + /* Adjust pointers so confounder is at start of header. */ + header->data.length -= hash->hashsize; + header->data.data += hash->hashsize; + + /* Compute the checksum using the usage key. */ + ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data, + &checksum); + if (ret != 0) + goto cleanup; + + /* Derive the encryption key from the usage key and checksum. */ + ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock); + if (ret) + goto cleanup; + + ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data); + +cleanup: + header->data = header_data; /* Restore header pointers. */ + krb5int_c_free_keyblock(NULL, usage_keyblock); + krb5int_c_free_keyblock(NULL, enc_keyblock); + return ret; +} + +krb5_error_code +krb5int_arcfour_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; + krb5_crypto_iov *header, *trailer; + krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL; + krb5_data checksum, header_data, comp_checksum = empty_data(); + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length != hash->hashsize + CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + + header_data = header->data; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL && trailer->data.length != 0) + return KRB5_BAD_MSIZE; + + /* Allocate buffers. */ + ret = alloc_data(&comp_checksum, hash->hashsize); + if (ret != 0) + goto cleanup; + ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, + &usage_keyblock); + if (ret != 0) + goto cleanup; + ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, + &enc_keyblock); + if (ret != 0) + goto cleanup; + + checksum = make_data(header->data.data, hash->hashsize); + + /* Adjust pointers so confounder is at start of header. */ + header->data.length -= hash->hashsize; + header->data.data += hash->hashsize; + + /* We may have to try two usage values; see below. */ + do { + /* Derive a usage key from the session key and usage. */ + ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive the encryption key from the usage key and checksum. */ + ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock); + if (ret) + goto cleanup; + + /* Decrypt the ciphertext. */ + ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + /* Compute HMAC(usage key, plaintext) to get the checksum. */ + ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data, + &comp_checksum); + if (ret != 0) + goto cleanup; + + if (k5_bcmp(checksum.data, comp_checksum.data, hash->hashsize) != 0) { + if (usage == 9) { + /* + * RFC 4757 specifies usage 8 for TGS-REP encrypted parts + * encrypted in a subkey, but the value used by MS is actually + * 9. We now use 9 to start with, but fall back to 8 on + * failure in case we are communicating with a KDC using the + * value from the RFC. ivec is always NULL in this case. + * We need to re-encrypt the data in the wrong key first. + */ + ret = keyblock_crypt(enc, enc_keyblock, NULL, data, num_data); + if (ret != 0) + goto cleanup; + usage = 8; + continue; + } + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + + break; + } while (1); + +cleanup: + header->data = header_data; /* Restore header pointers. */ + krb5int_c_free_keyblock(NULL, usage_keyblock); + krb5int_c_free_keyblock(NULL, enc_keyblock); + zapfree(comp_checksum.data, comp_checksum.length); + return ret; +} + +krb5_error_code +krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage, + const krb5_data *kd_data, krb5_crypto_iov *data, + size_t num_data) +{ + const struct krb5_enc_provider *enc = &krb5int_enc_arcfour; + const struct krb5_hash_provider *hash = &krb5int_hash_md5; + krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL; + krb5_error_code ret; + + ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes, + &usage_keyblock); + if (ret != 0) + goto cleanup; + ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes, + &enc_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive a usage key from the session key and usage. */ + ret = usage_key(enc, hash, keyblock, usage, usage_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive the encryption key from the usage key and kd_data. */ + ret = enc_key(enc, hash, usage_keyblock, kd_data, enc_keyblock); + if (ret != 0) + goto cleanup; + + /* Encrypt or decrypt (encrypt_iov works for both) the input. */ + ret = keyblock_crypt(enc, enc_keyblock, 0, data, num_data); + +cleanup: + krb5int_c_free_keyblock(NULL, usage_keyblock); + krb5int_c_free_keyblock(NULL, enc_keyblock); + return ret; +} diff --git a/src/lib/crypto/krb/encrypt.c b/src/lib/crypto/krb/encrypt.c new file mode 100644 index 000000000000..d9d575a4dd46 --- /dev/null +++ b/src/lib/crypto/krb/encrypt.c @@ -0,0 +1,94 @@ +/* -*- 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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_encrypt(krb5_context context, krb5_key key, + krb5_keyusage usage, const krb5_data *cipher_state, + const krb5_data *input, krb5_enc_data *output) +{ + const struct krb5_keytypes *ktp; + krb5_crypto_iov iov[4]; + krb5_error_code ret; + unsigned int header_len, padding_len, trailer_len, total_len; + + ktp = find_enctype(key->keyblock.enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + output->magic = KV5M_ENC_DATA; + output->kvno = 0; + output->enctype = key->keyblock.enctype; + + /* Get the lengths of the token parts and compute the total. */ + header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); + padding_len = krb5int_c_padding_length(ktp, input->length); + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + total_len = header_len + input->length + padding_len + trailer_len; + if (output->ciphertext.length < total_len) + return KRB5_BAD_MSIZE; + + /* Set up the iov structures for the token parts. */ + iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; + iov[0].data = make_data(output->ciphertext.data, header_len); + + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = make_data(output->ciphertext.data + header_len, + input->length); + if (input->length > 0) + memcpy(iov[1].data.data, input->data, input->length); + + iov[2].flags = KRB5_CRYPTO_TYPE_PADDING; + iov[2].data = make_data(iov[1].data.data + input->length, padding_len); + + iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER; + iov[3].data = make_data(iov[2].data.data + padding_len, trailer_len); + + ret = ktp->encrypt(ktp, key, usage, cipher_state, iov, 4); + if (ret != 0) + zap(iov[1].data.data, iov[1].data.length); + else + output->ciphertext.length = total_len; + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_encrypt(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *cipher_state, + const krb5_data *input, krb5_enc_data *output) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_encrypt(context, key, usage, cipher_state, input, output); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/encrypt_iov.c b/src/lib/crypto/krb/encrypt_iov.c new file mode 100644 index 000000000000..d66fcfa527e2 --- /dev/null +++ b/src/lib/crypto/krb/encrypt_iov.c @@ -0,0 +1,58 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/encrypt_iov.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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_encrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, + const krb5_data *cipher_state, krb5_crypto_iov *data, + size_t num_data) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(key->keyblock.enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + return ktp->encrypt(ktp, key, usage, cipher_state, data, num_data); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_encrypt_iov(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_encrypt_iov(context, key, usage, cipher_state, data, + num_data); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/encrypt_length.c b/src/lib/crypto/krb/encrypt_length.c new file mode 100644 index 000000000000..5428e429c707 --- /dev/null +++ b/src/lib/crypto/krb/encrypt_length.c @@ -0,0 +1,47 @@ +/* -*- 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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_encrypt_length(krb5_context context, krb5_enctype enctype, + size_t inputlen, size_t *length) +{ + const struct krb5_keytypes *ktp; + unsigned int header_len = 0, padding_len = 0, trailer_len = 0; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); + padding_len = krb5int_c_padding_length(ktp, inputlen); + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + + *length = header_len + inputlen + padding_len + trailer_len; + return 0; +} diff --git a/src/lib/crypto/krb/enctype_util.c b/src/lib/crypto/krb/enctype_util.c new file mode 100644 index 000000000000..0ed74bd6ebde --- /dev/null +++ b/src/lib/crypto/krb/enctype_util.c @@ -0,0 +1,133 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/enctype_util.c */ +/* + * 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. + */ + +/* + * krb5int_c_valid_enctype() + * krb5int_c_weak_enctype() + * krb5_c_enctype_compare() + * krb5_string_to_enctype() + * krb5_enctype_to_string() + */ + +#include "crypto_int.h" + +krb5_boolean KRB5_CALLCONV +krb5_c_valid_enctype(krb5_enctype etype) +{ + return (find_enctype(etype) != NULL); +} + +krb5_boolean KRB5_CALLCONV +krb5int_c_weak_enctype(krb5_enctype etype) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(etype); + return (ktp != NULL && (ktp->flags & ETYPE_WEAK) != 0); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_enctype_compare(krb5_context context, krb5_enctype e1, krb5_enctype e2, + krb5_boolean *similar) +{ + const struct krb5_keytypes *ktp1, *ktp2; + + ktp1 = find_enctype(e1); + ktp2 = find_enctype(e2); + if (ktp1 == NULL || ktp2 == NULL) + return KRB5_BAD_ENCTYPE; + + *similar = (ktp1->enc == ktp2->enc && ktp1->str2key == ktp2->str2key); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_string_to_enctype(char *string, krb5_enctype *enctypep) +{ + int i; + unsigned int j; + const char *alias; + const struct krb5_keytypes *ktp; + + for (i = 0; i < krb5int_enctypes_length; i++) { + ktp = &krb5int_enctypes_list[i]; + if (strcasecmp(ktp->name, string) == 0) { + *enctypep = ktp->etype; + return 0; + } + for (j = 0; j < MAX_ETYPE_ALIASES; j++) { + alias = ktp->aliases[j]; + if (alias == NULL) + break; + if (strcasecmp(alias, string) == 0) { + *enctypep = ktp->etype; + return 0; + } + } + } + + return EINVAL; +} + +krb5_error_code KRB5_CALLCONV +krb5_enctype_to_string(krb5_enctype enctype, char *buffer, size_t buflen) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return EINVAL; + if (strlcpy(buffer, ktp->out_string, buflen) >= buflen) + return ENOMEM; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_enctype_to_name(krb5_enctype enctype, krb5_boolean shortest, + char *buffer, size_t buflen) +{ + const struct krb5_keytypes *ktp; + const char *name; + int i; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return EINVAL; + name = ktp->name; + if (shortest) { + for (i = 0; i < MAX_ETYPE_ALIASES; i++) { + if (ktp->aliases[i] == NULL) + break; + if (strlen(ktp->aliases[i]) < strlen(name)) + name = ktp->aliases[i]; + } + } + if (strlcpy(buffer, name, buflen) >= buflen) + return ENOMEM; + return 0; +} diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c new file mode 100644 index 000000000000..0e5e977d418a --- /dev/null +++ b/src/lib/crypto/krb/etypes.c @@ -0,0 +1,194 @@ +/* -*- 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 "crypto_int.h" + +/* these will be linear searched. if they ever get big, a binary + search or hash table would be better, which means these would need + to be sorted. An array would be more efficient, but that assumes + that the keytypes are all near each other. I'd rather not make + that assumption. */ + +const struct krb5_keytypes krb5int_enctypes_list[] = { + { ENCTYPE_DES_CBC_CRC, + "des-cbc-crc", { 0 }, "DES cbc mode with CRC-32", + &krb5int_enc_des, &krb5int_hash_crc32, + 16, + krb5int_old_crypto_length, krb5int_old_encrypt, krb5int_old_decrypt, + krb5int_des_string_to_key, k5_rand2key_des, + krb5int_des_prf, + CKSUMTYPE_RSA_MD5_DES, + ETYPE_WEAK }, + { ENCTYPE_DES_CBC_MD4, + "des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4", + &krb5int_enc_des, &krb5int_hash_md4, + 16, + krb5int_old_crypto_length, krb5int_old_encrypt, krb5int_old_decrypt, + krb5int_des_string_to_key, k5_rand2key_des, + krb5int_des_prf, + CKSUMTYPE_RSA_MD4_DES, + ETYPE_WEAK }, + { ENCTYPE_DES_CBC_MD5, + "des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5", + &krb5int_enc_des, &krb5int_hash_md5, + 16, + krb5int_old_crypto_length, krb5int_old_encrypt, krb5int_old_decrypt, + krb5int_des_string_to_key, k5_rand2key_des, + krb5int_des_prf, + CKSUMTYPE_RSA_MD5_DES, + ETYPE_WEAK }, + { ENCTYPE_DES_CBC_RAW, + "des-cbc-raw", { 0 }, "DES cbc mode raw", + &krb5int_enc_des, NULL, + 16, + krb5int_raw_crypto_length, krb5int_raw_encrypt, krb5int_raw_decrypt, + krb5int_des_string_to_key, k5_rand2key_des, + krb5int_des_prf, + 0, + ETYPE_WEAK }, + { ENCTYPE_DES3_CBC_RAW, + "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw", + &krb5int_enc_des3, NULL, + 16, + krb5int_raw_crypto_length, krb5int_raw_encrypt, krb5int_raw_decrypt, + krb5int_dk_string_to_key, k5_rand2key_des3, + NULL, /*PRF*/ + 0, + ETYPE_WEAK }, + + { ENCTYPE_DES3_CBC_SHA1, + "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" }, + "Triple DES cbc mode with HMAC/sha1", + &krb5int_enc_des3, &krb5int_hash_sha1, + 16, + krb5int_dk_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt, + krb5int_dk_string_to_key, k5_rand2key_des3, + krb5int_dk_prf, + CKSUMTYPE_HMAC_SHA1_DES3, + 0 /*flags*/ }, + + { ENCTYPE_DES_HMAC_SHA1, + "des-hmac-sha1", { 0 }, "DES with HMAC/sha1", + &krb5int_enc_des, &krb5int_hash_sha1, + 8, + krb5int_dk_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt, + krb5int_dk_string_to_key, k5_rand2key_des, + NULL, /*PRF*/ + 0, + ETYPE_WEAK }, + { ENCTYPE_ARCFOUR_HMAC, + "arcfour-hmac", { "rc4-hmac", "arcfour-hmac-md5" }, + "ArcFour with HMAC/md5", + &krb5int_enc_arcfour, + &krb5int_hash_md5, + 20, + krb5int_arcfour_crypto_length, krb5int_arcfour_encrypt, + krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key, + k5_rand2key_direct, krb5int_arcfour_prf, + CKSUMTYPE_HMAC_MD5_ARCFOUR, + 0 /*flags*/ }, + { ENCTYPE_ARCFOUR_HMAC_EXP, + "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" }, + "Exportable ArcFour with HMAC/md5", + &krb5int_enc_arcfour, + &krb5int_hash_md5, + 20, + krb5int_arcfour_crypto_length, krb5int_arcfour_encrypt, + krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key, + k5_rand2key_direct, krb5int_arcfour_prf, + CKSUMTYPE_HMAC_MD5_ARCFOUR, + ETYPE_WEAK + }, + + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "aes128-cts-hmac-sha1-96", { "aes128-cts", "aes128-sha1" }, + "AES-128 CTS mode with 96-bit SHA-1 HMAC", + &krb5int_enc_aes128, &krb5int_hash_sha1, + 16, + krb5int_aes_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt, + krb5int_aes_string_to_key, k5_rand2key_direct, + krb5int_dk_prf, + CKSUMTYPE_HMAC_SHA1_96_AES128, + 0 /*flags*/ }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "aes256-cts-hmac-sha1-96", { "aes256-cts", "aes256-sha1" }, + "AES-256 CTS mode with 96-bit SHA-1 HMAC", + &krb5int_enc_aes256, &krb5int_hash_sha1, + 16, + krb5int_aes_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt, + krb5int_aes_string_to_key, k5_rand2key_direct, + krb5int_dk_prf, + CKSUMTYPE_HMAC_SHA1_96_AES256, + 0 /*flags*/ }, + + { ENCTYPE_CAMELLIA128_CTS_CMAC, + "camellia128-cts-cmac", { "camellia128-cts" }, + "Camellia-128 CTS mode with CMAC", + &krb5int_enc_camellia128, NULL, + 16, + krb5int_camellia_crypto_length, + krb5int_dk_cmac_encrypt, krb5int_dk_cmac_decrypt, + krb5int_camellia_string_to_key, k5_rand2key_direct, + krb5int_dk_cmac_prf, + CKSUMTYPE_CMAC_CAMELLIA128, + 0 /*flags*/ }, + { ENCTYPE_CAMELLIA256_CTS_CMAC, + "camellia256-cts-cmac", { "camellia256-cts" }, + "Camellia-256 CTS mode with CMAC", + &krb5int_enc_camellia256, NULL, + 16, + krb5int_camellia_crypto_length, + krb5int_dk_cmac_encrypt, krb5int_dk_cmac_decrypt, + krb5int_camellia_string_to_key, k5_rand2key_direct, + krb5int_dk_cmac_prf, + CKSUMTYPE_CMAC_CAMELLIA256, + 0 /*flags */ }, + + { ENCTYPE_AES128_CTS_HMAC_SHA256_128, + "aes128-cts-hmac-sha256-128", { "aes128-sha2" }, + "AES-128 CTS mode with 128-bit SHA-256 HMAC", + &krb5int_enc_aes128, &krb5int_hash_sha256, + 32, + krb5int_aes2_crypto_length, krb5int_etm_encrypt, krb5int_etm_decrypt, + krb5int_aes2_string_to_key, k5_rand2key_direct, + krb5int_aes2_prf, + CKSUMTYPE_HMAC_SHA256_128_AES128, + 0 /*flags*/ }, + { ENCTYPE_AES256_CTS_HMAC_SHA384_192, + "aes256-cts-hmac-sha384-192", { "aes256-sha2" }, + "AES-256 CTS mode with 192-bit SHA-384 HMAC", + &krb5int_enc_aes256, &krb5int_hash_sha384, + 48, + krb5int_aes2_crypto_length, krb5int_etm_encrypt, krb5int_etm_decrypt, + krb5int_aes2_string_to_key, k5_rand2key_direct, + krb5int_aes2_prf, + CKSUMTYPE_HMAC_SHA384_192_AES256, + 0 /*flags*/ }, +}; + +const int krb5int_enctypes_length = + sizeof(krb5int_enctypes_list) / sizeof(struct krb5_keytypes); diff --git a/src/lib/crypto/krb/key.c b/src/lib/crypto/krb/key.c new file mode 100644 index 000000000000..550ac20d376f --- /dev/null +++ b/src/lib/crypto/krb/key.c @@ -0,0 +1,110 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2009 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. + * + * Functions for manipulating krb5_key structures + */ + +#include "crypto_int.h" + +/* + * The krb5_key data type wraps an exposed keyblock in an opaque data + * structure, to allow for internal optimizations such as caching of + * derived keys. + */ + +/* Create a krb5_key from the enctype and key data in a keyblock. */ +krb5_error_code KRB5_CALLCONV +krb5_k_create_key(krb5_context context, const krb5_keyblock *key_data, + krb5_key *out) +{ + krb5_key key = NULL; + krb5_error_code code; + + *out = NULL; + + key = malloc(sizeof(*key)); + if (key == NULL) + return ENOMEM; + code = krb5int_c_copy_keyblock_contents(context, key_data, &key->keyblock); + if (code) + goto cleanup; + + key->refcount = 1; + key->derived = NULL; + key->cache = NULL; + *out = key; + return 0; + +cleanup: + free(key); + return code; +} + +void KRB5_CALLCONV +krb5_k_reference_key(krb5_context context, krb5_key key) +{ + if (key) + key->refcount++; +} + +/* Free the memory used by a krb5_key. */ +void KRB5_CALLCONV +krb5_k_free_key(krb5_context context, krb5_key key) +{ + struct derived_key *dk; + const struct krb5_keytypes *ktp; + + if (key == NULL || --key->refcount > 0) + return; + + /* Free the derived key cache. */ + while ((dk = key->derived) != NULL) { + key->derived = dk->next; + free(dk->constant.data); + krb5_k_free_key(context, dk->dkey); + free(dk); + } + krb5int_c_free_keyblock_contents(context, &key->keyblock); + if (key->cache) { + ktp = find_enctype(key->keyblock.enctype); + if (ktp && ktp->enc->key_cleanup) + ktp->enc->key_cleanup(key); + } + free(key); +} + +/* Retrieve a copy of the keyblock from a krb5_key. */ +krb5_error_code KRB5_CALLCONV +krb5_k_key_keyblock(krb5_context context, krb5_key key, + krb5_keyblock **key_data) +{ + return krb5int_c_copy_keyblock(context, &key->keyblock, key_data); +} + +/* Retrieve the enctype of a krb5_key. */ +krb5_enctype KRB5_CALLCONV +krb5_k_key_enctype(krb5_context context, krb5_key key) +{ + return key->keyblock.enctype; +} diff --git a/src/lib/crypto/krb/keyblocks.c b/src/lib/crypto/krb/keyblocks.c new file mode 100644 index 000000000000..98696f5086e1 --- /dev/null +++ b/src/lib/crypto/krb/keyblocks.c @@ -0,0 +1,108 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/keyblocks.c - Keyblock utility functions */ +/* + * Copyright (C) 2002, 2005 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 "crypto_int.h" + +krb5_error_code +krb5int_c_init_keyblock(krb5_context context, krb5_enctype enctype, + size_t length, krb5_keyblock **out) +{ + krb5_keyblock *kb; + + assert(out); + *out = NULL; + + kb = malloc(sizeof(krb5_keyblock)); + if (kb == NULL) + return ENOMEM; + kb->magic = KV5M_KEYBLOCK; + kb->enctype = enctype; + kb->length = length; + if (length) { + kb->contents = malloc(length); + if (!kb->contents) { + free(kb); + return ENOMEM; + } + } else { + kb->contents = NULL; + } + + *out = kb; + return 0; +} + +void +krb5int_c_free_keyblock(krb5_context context, register krb5_keyblock *val) +{ + krb5int_c_free_keyblock_contents(context, val); + free(val); +} + +void +krb5int_c_free_keyblock_contents(krb5_context context, krb5_keyblock *key) +{ + if (key && key->contents) { + zapfree(key->contents, key->length); + key->contents = NULL; + key->length = 0; + } +} + +krb5_error_code +krb5int_c_copy_keyblock(krb5_context context, const krb5_keyblock *from, + krb5_keyblock **to) +{ + krb5_keyblock *new_key; + krb5_error_code code; + + *to = NULL; + new_key = malloc(sizeof(*new_key)); + if (!new_key) + return ENOMEM; + code = krb5int_c_copy_keyblock_contents(context, from, new_key); + if (code) { + free(new_key); + return code; + } + *to = new_key; + return 0; +} + +krb5_error_code +krb5int_c_copy_keyblock_contents(krb5_context context, + const krb5_keyblock *from, krb5_keyblock *to) +{ + *to = *from; + if (to->length) { + to->contents = malloc(to->length); + if (!to->contents) + return ENOMEM; + memcpy(to->contents, from->contents, to->length); + } else + to->contents = 0; + return 0; +} diff --git a/src/lib/crypto/krb/keyed_checksum_types.c b/src/lib/crypto/krb/keyed_checksum_types.c new file mode 100644 index 000000000000..4b211fb46b69 --- /dev/null +++ b/src/lib/crypto/krb/keyed_checksum_types.c @@ -0,0 +1,82 @@ +/* -*- 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 "crypto_int.h" + +static krb5_boolean +is_keyed_for(const struct krb5_cksumtypes *ctp, + const struct krb5_keytypes *ktp) +{ + if (ctp->flags & CKSUM_UNKEYED) + return FALSE; + return (!ctp->enc || ktp->enc == ctp->enc); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype, + unsigned int *count, krb5_cksumtype **cksumtypes) +{ + unsigned int i, c, nctypes; + krb5_cksumtype *ctypes; + const struct krb5_cksumtypes *ctp; + const struct krb5_keytypes *ktp; + + *count = 0; + *cksumtypes = NULL; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + nctypes = 0; + for (i = 0; i < krb5int_cksumtypes_length; i++) { + ctp = &krb5int_cksumtypes_list[i]; + if (is_keyed_for(ctp, ktp)) + nctypes++; + } + + ctypes = malloc(nctypes * sizeof(krb5_cksumtype)); + if (ctypes == NULL) + return ENOMEM; + + c = 0; + for (i = 0; i < krb5int_cksumtypes_length; i++) { + ctp = &krb5int_cksumtypes_list[i]; + if (is_keyed_for(ctp, ktp)) + ctypes[c++] = ctp->ctype; + } + + *count = nctypes; + *cksumtypes = ctypes; + return 0; +} + +void KRB5_CALLCONV +krb5_free_cksumtypes(krb5_context context, krb5_cksumtype *val) +{ + free(val); +} diff --git a/src/lib/crypto/krb/keyed_cksum.c b/src/lib/crypto/krb/keyed_cksum.c new file mode 100644 index 000000000000..d3db8f31b706 --- /dev/null +++ b/src/lib/crypto/krb/keyed_cksum.c @@ -0,0 +1,39 @@ +/* -*- 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 "crypto_int.h" + +krb5_boolean KRB5_CALLCONV +krb5_c_is_keyed_cksum(krb5_cksumtype ctype) +{ + const struct krb5_cksumtypes *ctp; + + ctp = find_cksumtype(ctype); + if (ctp == NULL) + return FALSE; + return !(ctp->flags & CKSUM_UNKEYED); +} diff --git a/src/lib/crypto/krb/keylengths.c b/src/lib/crypto/krb/keylengths.c new file mode 100644 index 000000000000..2bbd1cc6bdec --- /dev/null +++ b/src/lib/crypto/krb/keylengths.c @@ -0,0 +1,57 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (c) 2006 + * The Regents of the University of Michigan + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#include "crypto_int.h" + +/* + * keybytes is the number of bytes required as input to make a key, + * keylength is the length of the final key in bytes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_keylengths(krb5_context context, krb5_enctype enctype, + size_t *keybytes, size_t *keylength) +{ + const struct krb5_keytypes *ktp; + + if (keybytes == NULL && keylength == NULL) + return EINVAL; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + if (keybytes) + *keybytes = ktp->enc->keybytes; + if (keylength) + *keylength = ktp->enc->keylength; + + return 0; +} diff --git a/src/lib/crypto/krb/make_checksum.c b/src/lib/crypto/krb/make_checksum.c new file mode 100644 index 000000000000..398c84a8dbb1 --- /dev/null +++ b/src/lib/crypto/krb/make_checksum.c @@ -0,0 +1,99 @@ +/* -*- 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 "crypto_int.h" + +/* A 0 checksum type means use the mandatory checksum. */ + +krb5_error_code KRB5_CALLCONV +krb5_k_make_checksum(krb5_context context, krb5_cksumtype cksumtype, + krb5_key key, krb5_keyusage usage, + const krb5_data *input, krb5_checksum *cksum) +{ + const struct krb5_cksumtypes *ctp; + krb5_crypto_iov iov; + krb5_data cksum_data; + krb5_octet *trunc; + krb5_error_code ret; + + if (cksumtype == 0) { + ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype, + &cksumtype); + if (ret != 0) + return ret; + } + ctp = find_cksumtype(cksumtype); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + ret = verify_key(ctp, key); + if (ret != 0) + return ret; + + ret = alloc_data(&cksum_data, ctp->compute_size); + if (ret != 0) + return ret; + + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *input; + ret = ctp->checksum(ctp, key, usage, &iov, 1, &cksum_data); + if (ret != 0) + goto cleanup; + + cksum->magic = KV5M_CHECKSUM; + cksum->checksum_type = cksumtype; + cksum->length = ctp->output_size; + cksum->contents = (krb5_octet *) cksum_data.data; + cksum_data.data = NULL; + if (ctp->output_size < ctp->compute_size) { + trunc = realloc(cksum->contents, ctp->output_size); + if (trunc != NULL) + cksum->contents = trunc; + } + +cleanup: + zapfree(cksum_data.data, ctp->compute_size); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype, + const krb5_keyblock *keyblock, krb5_keyusage usage, + const krb5_data *input, krb5_checksum *cksum) +{ + krb5_key key = NULL; + krb5_error_code ret; + + if (keyblock != NULL) { + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + } + ret = krb5_k_make_checksum(context, cksumtype, key, usage, input, cksum); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/make_checksum_iov.c b/src/lib/crypto/krb/make_checksum_iov.c new file mode 100644 index 000000000000..549180df515a --- /dev/null +++ b/src/lib/crypto/krb/make_checksum_iov.c @@ -0,0 +1,94 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/make_checksum_iov.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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_make_checksum_iov(krb5_context context, + krb5_cksumtype cksumtype, + krb5_key key, + krb5_keyusage usage, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + krb5_data cksum_data; + krb5_crypto_iov *checksum; + const struct krb5_cksumtypes *ctp; + + if (cksumtype == 0) { + ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype, + &cksumtype); + if (ret != 0) + return ret; + } + ctp = find_cksumtype(cksumtype); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + ret = verify_key(ctp, key); + if (ret != 0) + return ret; + + checksum = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM); + if (checksum == NULL || checksum->data.length < ctp->output_size) + return(KRB5_BAD_MSIZE); + + ret = alloc_data(&cksum_data, ctp->compute_size); + if (ret != 0) + return ret; + + ret = ctp->checksum(ctp, key, usage, data, num_data, &cksum_data); + if (ret != 0) + goto cleanup; + + memcpy(checksum->data.data, cksum_data.data, ctp->output_size); + checksum->data.length = ctp->output_size; + +cleanup: + zapfree(cksum_data.data, ctp->compute_size); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_make_checksum_iov(krb5_context context, + krb5_cksumtype cksumtype, + const krb5_keyblock *keyblock, + krb5_keyusage usage, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_make_checksum_iov(context, cksumtype, key, usage, + data, num_data); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/make_random_key.c b/src/lib/crypto/krb/make_random_key.c new file mode 100644 index 000000000000..f5af18780eb7 --- /dev/null +++ b/src/lib/crypto/krb/make_random_key.c @@ -0,0 +1,76 @@ +/* -*- 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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_make_random_key(krb5_context context, krb5_enctype enctype, + krb5_keyblock *random_key) +{ + krb5_error_code ret; + const struct krb5_keytypes *ktp; + const struct krb5_enc_provider *enc; + size_t keybytes, keylength; + krb5_data random_data; + unsigned char *bytes = NULL; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + enc = ktp->enc; + + keybytes = enc->keybytes; + keylength = enc->keylength; + + bytes = k5alloc(keybytes, &ret); + if (ret) + return ret; + random_key->contents = k5alloc(keylength, &ret); + if (ret) + goto cleanup; + + random_data.data = (char *) bytes; + random_data.length = keybytes; + + ret = krb5_c_random_make_octets(context, &random_data); + if (ret) + goto cleanup; + + random_key->magic = KV5M_KEYBLOCK; + random_key->enctype = enctype; + random_key->length = keylength; + + ret = (*ktp->rand2key)(&random_data, random_key); + +cleanup: + if (ret) { + zapfree(random_key->contents, keylength); + random_key->contents = NULL; + } + zapfree(bytes, keybytes); + return ret; +} diff --git a/src/lib/crypto/krb/mandatory_sumtype.c b/src/lib/crypto/krb/mandatory_sumtype.c new file mode 100644 index 000000000000..55ea81fa1803 --- /dev/null +++ b/src/lib/crypto/krb/mandatory_sumtype.c @@ -0,0 +1,39 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2003 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 "crypto_int.h" + +krb5_error_code +krb5int_c_mandatory_cksumtype(krb5_context ctx, krb5_enctype etype, + krb5_cksumtype *cksumtype) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(etype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + *cksumtype = ktp->required_ctype; + return 0; +} diff --git a/src/lib/crypto/krb/nfold.c b/src/lib/crypto/krb/nfold.c new file mode 100644 index 000000000000..ea02fddcf060 --- /dev/null +++ b/src/lib/crypto/krb/nfold.c @@ -0,0 +1,127 @@ +/* -*- 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 "crypto_int.h" + +/* + * n-fold(k-bits): + * l = lcm(n,k) + * r = l/k + * s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1) + * compute the 1's complement sum: + * n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1] + */ + +/* representation: msb first, assume n and k are multiples of 8, and + * that k>=16. this is the case of all the cryptosystems which are + * likely to be used. this function can be replaced if that + * assumption ever fails. */ + +/* input length is in bits */ + +void +krb5int_nfold(unsigned int inbits, const unsigned char *in, unsigned int outbits, + unsigned char *out) +{ + int a,b,c,lcm; + int byte, i, msbit; + + /* the code below is more readable if I make these bytes + instead of bits */ + + inbits >>= 3; + outbits >>= 3; + + /* first compute lcm(n,k) */ + + a = outbits; + b = inbits; + + while(b != 0) { + c = b; + b = a%b; + a = c; + } + + lcm = outbits*inbits/a; + + /* now do the real work */ + + memset(out, 0, outbits); + byte = 0; + + /* this will end up cycling through k lcm(k,n)/k times, which + is correct */ + for (i=lcm-1; i>=0; i--) { + /* compute the msbit in k which gets added into this byte */ + msbit = (/* first, start with the msbit in the first, unrotated + byte */ + ((inbits<<3)-1) + /* then, for each byte, shift to the right for each + repetition */ + +(((inbits<<3)+13)*(i/inbits)) + /* last, pick out the correct byte within that + shifted repetition */ + +((inbits-(i%inbits))<<3) + )%(inbits<<3); + + /* pull out the byte value itself */ + byte += (((in[((inbits-1)-(msbit>>3))%inbits]<<8)| + (in[((inbits)-(msbit>>3))%inbits])) + >>((msbit&7)+1))&0xff; + + /* do the addition */ + byte += out[i%outbits]; + out[i%outbits] = byte&0xff; + +#if 0 + printf("msbit[%d] = %d\tbyte = %02x\tsum = %03x\n", i, msbit, + (((in[((inbits-1)-(msbit>>3))%inbits]<<8)| + (in[((inbits)-(msbit>>3))%inbits])) + >>((msbit&7)+1))&0xff, byte); +#endif + + /* keep around the carry bit, if any */ + byte >>= 8; + +#if 0 + printf("carry=%d\n", byte); +#endif + } + + /* if there's a carry bit left over, add it back in */ + if (byte) { + for (i=outbits-1; i>=0; i--) { + /* do the addition */ + byte += out[i]; + out[i] = byte&0xff; + + /* keep around the carry bit, if any */ + byte >>= 8; + } + } +} diff --git a/src/lib/crypto/krb/old_api_glue.c b/src/lib/crypto/krb/old_api_glue.c new file mode 100644 index 000000000000..b5bb280833fa --- /dev/null +++ b/src/lib/crypto/krb/old_api_glue.c @@ -0,0 +1,390 @@ +/* -*- 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 "crypto_int.h" + +/* + * The following functions were removed from the API in krb5 1.3 but + * still need to be exported for ABI compatibility. The other + * functions defined in this file are still in the API (and thus + * prototyped in krb5.hin) but are deprecated. + */ +krb5_boolean KRB5_CALLCONV valid_enctype(krb5_enctype ktype); +krb5_boolean KRB5_CALLCONV valid_cksumtype(krb5_cksumtype ctype); +krb5_boolean KRB5_CALLCONV is_coll_proof_cksum(krb5_cksumtype ctype); +krb5_boolean KRB5_CALLCONV is_keyed_cksum(krb5_cksumtype ctype); +krb5_error_code KRB5_CALLCONV krb5_random_confounder(size_t, krb5_pointer); +krb5_error_code krb5_encrypt_data(krb5_context context, krb5_keyblock *key, + krb5_pointer ivec, krb5_data *data, + krb5_enc_data *enc_data); +krb5_error_code krb5_decrypt_data(krb5_context context, krb5_keyblock *key, + krb5_pointer ivec, krb5_enc_data *data, + krb5_data *enc_data); + +krb5_error_code KRB5_CALLCONV +krb5_encrypt(krb5_context context, krb5_const_pointer inptr, + krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock, + krb5_pointer ivec) +{ + krb5_data inputd, ivecd; + krb5_enc_data outputd; + size_t blocksize, outlen; + krb5_error_code ret; + + if (ivec) { + ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize); + if (ret) + return ret; + + ivecd = make_data(ivec, blocksize); + } + + /* size is the length of the input cleartext data. */ + inputd = make_data((void *) inptr, size); + + /* + * The size of the output buffer isn't part of the old api. Not too + * safe. So, we assume here that it's big enough. + */ + ret = krb5_c_encrypt_length(context, eblock->key->enctype, size, &outlen); + if (ret) + return ret; + + outputd.ciphertext = make_data(outptr, outlen); + + return krb5_c_encrypt(context, eblock->key, 0, ivec ? &ivecd : 0, + &inputd, &outputd); +} + +krb5_error_code KRB5_CALLCONV +krb5_decrypt(krb5_context context, krb5_const_pointer inptr, + krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock, + krb5_pointer ivec) +{ + krb5_enc_data inputd; + krb5_data outputd, ivecd; + size_t blocksize; + krb5_error_code ret; + + if (ivec) { + ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize); + if (ret) + return ret; + + ivecd = make_data(ivec, blocksize); + } + + /* size is the length of the input ciphertext data */ + inputd.enctype = eblock->key->enctype; + inputd.ciphertext = make_data((void *) inptr, size); + + /* we don't really know how big this is, but the code tends to assume + that the output buffer size should be the same as the input + buffer size */ + outputd = make_data(outptr, size); + + return krb5_c_decrypt(context, eblock->key, 0, ivec ? &ivecd : 0, + &inputd, &outputd); +} + +krb5_error_code KRB5_CALLCONV +krb5_process_key(krb5_context context, krb5_encrypt_block *eblock, + const krb5_keyblock *key) +{ + eblock->key = (krb5_keyblock *) key; + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_finish_key(krb5_context context, krb5_encrypt_block *eblock) +{ + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_string_to_key(krb5_context context, const krb5_encrypt_block *eblock, + krb5_keyblock *keyblock, const krb5_data *data, + const krb5_data *salt) +{ + return krb5_c_string_to_key(context, eblock->crypto_entry, data, salt, + keyblock); +} + +krb5_error_code KRB5_CALLCONV +krb5_init_random_key(krb5_context context, const krb5_encrypt_block *eblock, + const krb5_keyblock *keyblock, krb5_pointer *ptr) +{ + krb5_data data = make_data(keyblock->contents, keyblock->length); + + return krb5_c_random_seed(context, &data); +} + +krb5_error_code KRB5_CALLCONV +krb5_finish_random_key(krb5_context context, const krb5_encrypt_block *eblock, + krb5_pointer *ptr) +{ + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_random_key(krb5_context context, const krb5_encrypt_block *eblock, + krb5_pointer ptr, krb5_keyblock **keyblock) +{ + krb5_keyblock *key; + krb5_error_code ret; + + *keyblock = NULL; + + key = malloc(sizeof(krb5_keyblock)); + if (key == NULL) + return ENOMEM; + + ret = krb5_c_make_random_key(context, eblock->crypto_entry, key); + if (ret) { + free(key); + return ret; + } + + *keyblock = key; + return(ret); +} + +krb5_enctype KRB5_CALLCONV +krb5_eblock_enctype(krb5_context context, const krb5_encrypt_block *eblock) +{ + return eblock->crypto_entry; +} + +krb5_error_code KRB5_CALLCONV +krb5_use_enctype(krb5_context context, krb5_encrypt_block *eblock, + krb5_enctype enctype) +{ + eblock->crypto_entry = enctype; + + return 0; +} + +size_t KRB5_CALLCONV +krb5_encrypt_size(size_t length, krb5_enctype crypto) +{ + size_t ret; + + if (krb5_c_encrypt_length(NULL, crypto, length, &ret)) + return (size_t) -1; /* XXX */ + + return ret; +} + +size_t KRB5_CALLCONV +krb5_checksum_size(krb5_context context, krb5_cksumtype ctype) +{ + size_t ret; + + if (krb5_c_checksum_length(context, ctype, &ret)) + return (size_t) -1; /* XXX */ + + return ret; +} + +/* Guess the enctype for an untyped key used with checksum type ctype. */ +static krb5_enctype +guess_enctype(krb5_cksumtype ctype) +{ + const struct krb5_cksumtypes *ctp; + int i; + + if (ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) + return ENCTYPE_ARCFOUR_HMAC; + ctp = find_cksumtype(ctype); + if (ctp == NULL || ctp->enc == NULL) + return 0; + for (i = 0; i < krb5int_enctypes_length; i++) { + if (krb5int_enctypes_list[i].enc == ctp->enc) + return i; + } + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_calculate_checksum(krb5_context context, krb5_cksumtype ctype, + krb5_const_pointer in, size_t in_length, + krb5_const_pointer seed, size_t seed_length, + krb5_checksum *outcksum) +{ + krb5_data input = make_data((void *) in, in_length); + krb5_keyblock keyblock, *kptr = NULL; + krb5_error_code ret; + krb5_checksum cksum; + + if (seed != NULL) { + keyblock.enctype = guess_enctype(ctype); + keyblock.length = seed_length; + keyblock.contents = (unsigned char *) seed; + kptr = &keyblock; + } + + ret = krb5_c_make_checksum(context, ctype, kptr, 0, &input, &cksum); + if (ret) + return ret; + + if (outcksum->length < cksum.length) { + memset(cksum.contents, 0, cksum.length); + free(cksum.contents); + return KRB5_BAD_MSIZE; + } + + outcksum->magic = cksum.magic; + outcksum->checksum_type = cksum.checksum_type; + memcpy(outcksum->contents, cksum.contents, cksum.length); + outcksum->length = cksum.length; + + free(cksum.contents); + + return(0); +} + +krb5_error_code KRB5_CALLCONV +krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype, + const krb5_checksum *cksum, krb5_const_pointer in, + size_t in_length, krb5_const_pointer seed, + size_t seed_length) +{ + krb5_data input = make_data((void *) in, in_length); + krb5_keyblock keyblock, *kptr = NULL; + krb5_error_code ret; + krb5_boolean valid; + + if (seed != NULL) { + keyblock.enctype = guess_enctype(ctype); + keyblock.length = seed_length; + keyblock.contents = (unsigned char *) seed; + kptr = &keyblock; + } + + ret = krb5_c_verify_checksum(context, kptr, 0, &input, cksum, &valid); + if (ret) + return ret; + + if (!valid) + return KRB5KRB_AP_ERR_BAD_INTEGRITY; + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_random_confounder(size_t size, krb5_pointer ptr) +{ + krb5_data random_data = make_data(ptr, size); + + return krb5_c_random_make_octets(NULL, &random_data); +} + +krb5_error_code krb5_encrypt_data(krb5_context context, krb5_keyblock *key, + krb5_pointer ivec, krb5_data *data, + krb5_enc_data *enc_data) +{ + krb5_error_code ret; + size_t enclen, blocksize; + krb5_data ivecd; + + ret = krb5_c_encrypt_length(context, key->enctype, data->length, &enclen); + if (ret) + return ret; + + if (ivec) { + ret = krb5_c_block_size(context, key->enctype, &blocksize); + if (ret) + return ret; + + ivecd = make_data(ivec, blocksize); + } + + enc_data->magic = KV5M_ENC_DATA; + enc_data->kvno = 0; + enc_data->enctype = key->enctype; + ret = alloc_data(&enc_data->ciphertext, enclen); + if (ret) + return ret; + + ret = krb5_c_encrypt(context, key, 0, ivec ? &ivecd : 0, data, enc_data); + if (ret) + free(enc_data->ciphertext.data); + + return ret; +} + +krb5_error_code krb5_decrypt_data(krb5_context context, krb5_keyblock *key, + krb5_pointer ivec, krb5_enc_data *enc_data, + krb5_data *data) +{ + krb5_error_code ret; + krb5_data ivecd; + size_t blocksize; + + if (ivec) { + ret = krb5_c_block_size(context, key->enctype, &blocksize); + if (ret) + return ret; + + ivecd = make_data(ivec, blocksize); + } + + ret = alloc_data(data, enc_data->ciphertext.length); + if (ret) + return ret; + + ret = krb5_c_decrypt(context, key, 0, ivec ? &ivecd : 0, enc_data, data); + if (ret) + free(data->data); + + return 0; +} + +krb5_boolean KRB5_CALLCONV +valid_cksumtype(krb5_cksumtype ctype) +{ + return krb5_c_valid_cksumtype(ctype); +} + +krb5_boolean KRB5_CALLCONV +is_keyed_cksum(krb5_cksumtype ctype) +{ + return krb5_c_is_keyed_cksum(ctype); +} + +krb5_boolean KRB5_CALLCONV +is_coll_proof_cksum(krb5_cksumtype ctype) +{ + return krb5_c_is_coll_proof_cksum(ctype); +} + +krb5_boolean KRB5_CALLCONV +valid_enctype(krb5_enctype etype) +{ + return krb5_c_valid_enctype(etype); +} diff --git a/src/lib/crypto/krb/prf.c b/src/lib/crypto/krb/prf.c new file mode 100644 index 000000000000..67b856a9b6c0 --- /dev/null +++ b/src/lib/crypto/krb/prf.c @@ -0,0 +1,84 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf.c */ +/* + * Copyright (C) 2004 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. + */ + +/* + * This contains the implementation of krb5_c_prf, which will find the + * enctype-specific PRF and then generate pseudo-random data. This function + * yields krb5_c_prf_length bytes of output. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_prf_length(krb5_context context, krb5_enctype enctype, size_t *len) +{ + const struct krb5_keytypes *ktp; + + assert(len); + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + *len = ktp->prf_length; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_k_prf(krb5_context context, krb5_key key, + krb5_data *input, krb5_data *output) +{ + const struct krb5_keytypes *ktp; + krb5_error_code ret; + + assert(input && output); + assert(output->data); + + ktp = find_enctype(key->keyblock.enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + if (ktp->prf == NULL) + return KRB5_CRYPTO_INTERNAL; + + output->magic = KV5M_DATA; + if (ktp->prf_length != output->length) + return KRB5_CRYPTO_INTERNAL; + ret = ktp->prf(ktp, key, input, output); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_prf(krb5_context context, const krb5_keyblock *keyblock, + krb5_data *input, krb5_data *output) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_prf(context, key, input, output); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/prf_aes2.c b/src/lib/crypto/krb/prf_aes2.c new file mode 100644 index 000000000000..9a5cffc56cb2 --- /dev/null +++ b/src/lib/crypto/krb/prf_aes2.c @@ -0,0 +1,42 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf_aes2.c - PRF for aes-sha2 enctypes */ +/* + * Copyright (C) 2015 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_aes2_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out) +{ + krb5_data label = string2data("prf"); + + return k5_sp800_108_counter_hmac(ktp->hash, key, out, &label, in); +} diff --git a/src/lib/crypto/krb/prf_cmac.c b/src/lib/crypto/krb/prf_cmac.c new file mode 100644 index 000000000000..1d4cc4c39501 --- /dev/null +++ b/src/lib/crypto/krb/prf_cmac.c @@ -0,0 +1,58 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf_cmac.c - CMAC-based PRF */ +/* + * Copyright (C) 2010 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 "crypto_int.h" + +krb5_error_code +krb5int_dk_cmac_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out) +{ + krb5_crypto_iov iov; + krb5_data prfconst = make_data("prf", 3); + krb5_key kp = NULL; + krb5_error_code ret; + + if (ktp->prf_length != ktp->enc->block_size) + return KRB5_BAD_MSIZE; + + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *in; + + /* Derive a key using the PRF constant. */ + ret = krb5int_derive_key(ktp->enc, NULL, key, &kp, &prfconst, + DERIVE_SP800_108_CMAC); + if (ret != 0) + goto cleanup; + + /* PRF is CMAC of input */ + ret = krb5int_cmac_checksum(ktp->enc, kp, &iov, 1, out); + if (ret != 0) + goto cleanup; + +cleanup: + krb5_k_free_key(NULL, kp); + return ret; +} diff --git a/src/lib/crypto/krb/prf_des.c b/src/lib/crypto/krb/prf_des.c new file mode 100644 index 000000000000..7a2d719c5f9f --- /dev/null +++ b/src/lib/crypto/krb/prf_des.c @@ -0,0 +1,47 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf_des.c - RFC 3961 DES-based PRF */ +/* + * Copyright (C) 2004, 2009 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 "crypto_int.h" + +krb5_error_code +krb5int_des_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out) +{ + const struct krb5_hash_provider *hash = &krb5int_hash_md5; + krb5_crypto_iov iov; + krb5_error_code ret; + + /* Compute a hash of the input, storing into the output buffer. */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *in; + ret = hash->hash(&iov, 1, out); + if (ret != 0) + return ret; + + /* Encrypt the hash in place. */ + iov.data = *out; + return ktp->enc->encrypt(key, NULL, &iov, 1); +} diff --git a/src/lib/crypto/krb/prf_dk.c b/src/lib/crypto/krb/prf_dk.c new file mode 100644 index 000000000000..544418bab74e --- /dev/null +++ b/src/lib/crypto/krb/prf_dk.c @@ -0,0 +1,70 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf_dk.c - RFC 3961 simplified profile PRF */ +/* + * Copyright (C) 2004 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 "crypto_int.h" + +krb5_error_code +krb5int_dk_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out) +{ + const struct krb5_enc_provider *enc = ktp->enc; + const struct krb5_hash_provider *hash = ktp->hash; + krb5_crypto_iov iov; + krb5_data cksum = empty_data(), prfconst = make_data("prf", 3); + krb5_key kp = NULL; + krb5_error_code ret; + + /* Hash the input data into an allocated buffer. */ + ret = alloc_data(&cksum, hash->hashsize); + if (ret != 0) + goto cleanup; + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *in; + ret = hash->hash(&iov, 1, &cksum); + if (ret != 0) + goto cleanup; + + /* Derive a key using the PRF constant. */ + ret = krb5int_derive_key(ktp->enc, NULL, key, &kp, &prfconst, + DERIVE_RFC3961); + if (ret != 0) + goto cleanup; + + /* Truncate the hash to the closest multiple of the block size. */ + iov.data.data = cksum.data; + iov.data.length = (hash->hashsize / enc->block_size) * enc->block_size; + + /* Encrypt the truncated hash in the derived key to get the output. */ + ret = ktp->enc->encrypt(kp, NULL, &iov, 1); + if (ret != 0) + goto cleanup; + memcpy(out->data, iov.data.data, out->length); + +cleanup: + zapfree(cksum.data, hash->hashsize); + krb5_k_free_key(NULL, kp); + return ret; +} diff --git a/src/lib/crypto/krb/prf_rc4.c b/src/lib/crypto/krb/prf_rc4.c new file mode 100644 index 000000000000..092795321e51 --- /dev/null +++ b/src/lib/crypto/krb/prf_rc4.c @@ -0,0 +1,39 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf_rc4.c */ +/* + * Copyright (C) 2009 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 "crypto_int.h" + +krb5_error_code +krb5int_arcfour_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out) +{ + krb5_crypto_iov iov; + + assert(out->length == 20); + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *in; + return krb5int_hmac(&krb5int_hash_sha1, key, &iov, 1, out); +} diff --git a/src/lib/crypto/krb/prng.c b/src/lib/crypto/krb/prng.c new file mode 100644 index 000000000000..cb9ca9b983d1 --- /dev/null +++ b/src/lib/crypto/krb/prng.c @@ -0,0 +1,134 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2001, 2002, 2004, 2007, 2008, 2010 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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_random_seed(krb5_context context, krb5_data *data) +{ + return krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_OLDAPI, data); +} + +/* Routines to get entropy from the OS. */ +#if defined(_WIN32) + +krb5_boolean +k5_get_os_entropy(unsigned char *buf, size_t len, int strong) +{ + krb5_boolean result; + HCRYPTPROV provider; + + /* CryptGenRandom is always considered strong. */ + + if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) + return FALSE; + result = CryptGenRandom(provider, len, buf); + (void)CryptReleaseContext(provider, 0); + return result; +} + +#else /* not Windows */ +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef __linux__ +#include <sys/syscall.h> +#endif /* __linux__ */ + +/* Open device, ensure that it is not a regular file, and read entropy. Return + * true on success, false on failure. */ +static krb5_boolean +read_entropy_from_device(const char *device, unsigned char *buf, size_t len) +{ + struct stat sb; + int fd; + unsigned char *bp; + size_t left; + ssize_t count; + krb5_boolean result = FALSE; + + fd = open(device, O_RDONLY); + if (fd == -1) + return FALSE; + set_cloexec_fd(fd); + if (fstat(fd, &sb) == -1 || S_ISREG(sb.st_mode)) + goto cleanup; + + for (bp = buf, left = len; left > 0;) { + count = read(fd, bp, left); + if (count <= 0) + goto cleanup; + left -= count; + bp += count; + } + result = TRUE; + +cleanup: + close(fd); + return result; +} + +krb5_boolean +k5_get_os_entropy(unsigned char *buf, size_t len, int strong) +{ + const char *device; +#if defined(__linux__) && defined(SYS_getrandom) + int r; + + while (len > 0) { + /* + * Pull from the /dev/urandom pool, but require it to have been seeded. + * This ensures strong randomness while only blocking during first + * system boot. + * + * glibc does not currently provide a binding for getrandom: + * https://sourceware.org/bugzilla/show_bug.cgi?id=17252 + */ + errno = 0; + r = syscall(SYS_getrandom, buf, len, 0); + if (r <= 0) { + if (errno == EINTR) + continue; + + /* ENOSYS or other unrecoverable failure */ + break; + } + len -= r; + buf += r; + } + if (len == 0) + return TRUE; +#endif /* defined(__linux__) && defined(SYS_getrandom) */ + + device = strong ? "/dev/random" : "/dev/urandom"; + return read_entropy_from_device(device, buf, len); +} + +#endif /* not Windows */ diff --git a/src/lib/crypto/krb/prng_device.c b/src/lib/crypto/krb/prng_device.c new file mode 100644 index 000000000000..bef5b3752416 --- /dev/null +++ b/src/lib/crypto/krb/prng_device.c @@ -0,0 +1,99 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prng_device.c - OS device-based PRNG implementation */ +/* + * Copyright (C) 2011 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. + */ + +/* + * This file implements a PRNG module which relies on the system's /dev/urandom + * device. An OS packager can select this module given sufficient confidence + * in the operating system's native PRNG quality. + */ + +#include "crypto_int.h" + +#define DEVICE "/dev/urandom" + +static int fd = -1; + +int +k5_prng_init(void) +{ + /* Try to open the random device read-write; if that fails, read-only is + * okay. */ + fd = open(DEVICE, O_RDWR, 0); + if (fd == -1) + fd = open(DEVICE, O_RDONLY, 0); + if (fd == -1) + return errno; + return 0; +} + +void +k5_prng_cleanup(void) +{ + close(fd); + fd = -1; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_random_add_entropy(krb5_context context, unsigned int randsource, + const krb5_data *indata) +{ + krb5_error_code ret; + + ret = krb5int_crypto_init(); + if (ret) + return ret; + + /* Some random devices let user-space processes contribute entropy. Don't + * worry if this fails. */ + (void)write(fd, indata->data, indata->length); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_random_make_octets(krb5_context context, krb5_data *outdata) +{ + char *buf = outdata->data; + size_t len = outdata->length; + ssize_t count; + + while (len > 0) { + count = read(fd, buf, len); + if (count == 0) /* Not expected from a random device. */ + return KRB5_CRYPTO_INTERNAL; + if (count == -1) + return errno; + buf += count; + len -= count; + } + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_random_os_entropy(krb5_context context, int strong, int *success) +{ + return 0; +} diff --git a/src/lib/crypto/krb/prng_fortuna.c b/src/lib/crypto/krb/prng_fortuna.c new file mode 100644 index 000000000000..017a119cc460 --- /dev/null +++ b/src/lib/crypto/krb/prng_fortuna.c @@ -0,0 +1,470 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prng_fortuna.c - Fortuna PRNG implementation */ +/* + * Copyright (c) 2005 Marko Kreen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (C) 2010, 2011 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. + */ + +/* + * This file implements the generator and accumulator parts of the Fortuna PRNG + * as described in chapter 9 of _Cryptography Engineering_ by Ferguson, + * Schneier, and Kohno. + * + * The generator, once seeded with an unguessable value, produces an unlimited + * number of pseudo-random outputs which cannot be used to determine the + * internal state of the generator (without an unreasonable amount of + * computational power). The generator protects against the case where the OS + * random number generator is not cryptographically secure, but can produce an + * unguessable initial seed. Successive reseeds of the generator will not make + * the internal state any more guessable than it was before. + * + * The accumulator is layered on top of the generator, and seeks to eventually + * recover from the case where the OS random number generator did not produce + * an unguessable initial seed. Unreliable entropy inputs are collected into + * 32 pools, which are used to reseed the generator when enough entropy has + * been collected. Each pool collects twice as much entropy between reseeds as + * the previous one; eventually a reseed will occur involving a pool with + * enough entropy that an attacker cannot maintain knowledge of the generator's + * internal state. The accumulator is only helpful for a long-running process + * such as a KDC which can submit periodic entropy inputs to the PRNG. + */ + +#include "crypto_int.h" + +/* The accumulator's number of pools. */ +#define NUM_POOLS 32 + +/* Minimum reseed interval in microseconds. */ +#define RESEED_INTERVAL 100000 /* 0.1 sec */ + +/* For one big request, change the key after this many bytes. */ +#define MAX_BYTES_PER_KEY (1 << 20) + +/* Reseed if pool 0 has had this many bytes added since last reseed. */ +#define MIN_POOL_LEN 64 + +/* AES-256 key size in bytes. */ +#define AES256_KEYSIZE (256/8) + +/* AES-256 block size in bytes. */ +#define AES256_BLOCKSIZE (128/8) + +/* SHA-256 block size in bytes. */ +#define SHA256_BLOCKSIZE (512/8) + +/* SHA-256 result size in bytes. */ +#define SHA256_HASHSIZE (256/8) + +/* Genarator - block cipher in CTR mode */ +struct fortuna_state +{ + /* Generator state. */ + unsigned char counter[AES256_BLOCKSIZE]; + unsigned char key[AES256_KEYSIZE]; + aes_ctx ciph; + + /* Accumulator state. */ + SHA256_CTX pool[NUM_POOLS]; + unsigned int pool_index; + unsigned int reseed_count; + struct timeval last_reseed_time; + unsigned int pool0_bytes; +}; + +/* + * SHA[d]-256(m) is defined as SHA-256(SHA-256(0^512||m))--that is, hash a + * block full of zeros followed by the input data, then re-hash the result. + * These functions implement the SHA[d]-256 function on incremental inputs. + */ + +static void +shad256_init(SHA256_CTX *ctx) +{ + unsigned char zero[SHA256_BLOCKSIZE]; + + /* Initialize the inner SHA-256 context and update it with a zero block. */ + memset(zero, 0, sizeof(zero)); + k5_sha256_init(ctx); + k5_sha256_update(ctx, zero, sizeof(zero)); +} + +static void +shad256_update(SHA256_CTX *ctx, const unsigned char *data, int len) +{ + /* Feed the input to the inner SHA-256 context. */ + k5_sha256_update(ctx, data, len); +} + +static void +shad256_result(SHA256_CTX *ctx, unsigned char *dst) +{ + /* Finalize the inner context, then feed the result back through SHA256. */ + k5_sha256_final(dst, ctx); + k5_sha256_init(ctx); + k5_sha256_update(ctx, dst, SHA256_HASHSIZE); + k5_sha256_final(dst, ctx); +} + +/* Initialize state. */ +static void +init_state(struct fortuna_state *st) +{ + unsigned int i; + + memset(st, 0, sizeof(*st)); + for (i = 0; i < NUM_POOLS; i++) + shad256_init(&st->pool[i]); +} + +/* Increment st->counter using least significant byte first. */ +static void +inc_counter(struct fortuna_state *st) +{ + uint64_t val; + + val = load_64_le(st->counter) + 1; + store_64_le(val, st->counter); + if (val == 0) { + val = load_64_le(st->counter + 8) + 1; + store_64_le(val, st->counter + 8); + } +} + +/* Encrypt and increment st->counter in the current cipher context. */ +static void +encrypt_counter(struct fortuna_state *st, unsigned char *dst) +{ + krb5int_aes_enc_blk(st->counter, dst, &st->ciph); + inc_counter(st); +} + +/* Reseed the generator based on hopefully non-guessable input. */ +static void +generator_reseed(struct fortuna_state *st, const unsigned char *data, + size_t len) +{ + SHA256_CTX ctx; + + /* Calculate SHA[d]-256(key||s) and make that the new key. Depend on the + * SHA-256 hash size being the AES-256 key size. */ + shad256_init(&ctx); + shad256_update(&ctx, st->key, AES256_KEYSIZE); + shad256_update(&ctx, data, len); + shad256_result(&ctx, st->key); + zap(&ctx, sizeof(ctx)); + krb5int_aes_enc_key(st->key, AES256_KEYSIZE, &st->ciph); + + /* Increment counter. */ + inc_counter(st); +} + +/* Generate two blocks in counter mode and replace the key with the result. */ +static void +change_key(struct fortuna_state *st) +{ + encrypt_counter(st, st->key); + encrypt_counter(st, st->key + AES256_BLOCKSIZE); + krb5int_aes_enc_key(st->key, AES256_KEYSIZE, &st->ciph); +} + +/* Output pseudo-random data from the generator. */ +static void +generator_output(struct fortuna_state *st, unsigned char *dst, size_t len) +{ + unsigned char result[AES256_BLOCKSIZE]; + size_t n, count = 0; + + while (len > 0) { + /* Produce bytes and copy the result into dst. */ + encrypt_counter(st, result); + n = (len < AES256_BLOCKSIZE) ? len : AES256_BLOCKSIZE; + memcpy(dst, result, n); + dst += n; + len -= n; + + /* Each time we reach MAX_BYTES_PER_KEY bytes, change the key. */ + count += AES256_BLOCKSIZE; + if (count >= MAX_BYTES_PER_KEY) { + change_key(st); + count = 0; + } + } + zap(result, sizeof(result)); + + /* Change the key after each request. */ + change_key(st); +} + +/* Reseed the generator using the accumulator pools. */ +static void +accumulator_reseed(struct fortuna_state *st) +{ + unsigned int i, n; + SHA256_CTX ctx; + unsigned char hash_result[SHA256_HASHSIZE]; + + n = ++st->reseed_count; + + /* + * Collect entropy from pools. We use the i-th pool only 1/(2^i) of the + * time so that each pool collects twice as much entropy between uses as + * the last. + */ + shad256_init(&ctx); + for (i = 0; i < NUM_POOLS; i++) { + if (n % (1 << i) != 0) + break; + + /* Harvest this pool's hash result into ctx, then reset the pool. */ + shad256_result(&st->pool[i], hash_result); + shad256_init(&st->pool[i]); + shad256_update(&ctx, hash_result, SHA256_HASHSIZE); + } + shad256_result(&ctx, hash_result); + generator_reseed(st, hash_result, SHA256_HASHSIZE); + zap(hash_result, SHA256_HASHSIZE); + zap(&ctx, sizeof(ctx)); + + /* Reset the count of bytes added to pool 0. */ + st->pool0_bytes = 0; +} + +/* Add possibly unguessable data to the next accumulator pool. */ +static void +accumulator_add_event(struct fortuna_state *st, const unsigned char *data, + size_t len) +{ + unsigned char lenbuf[2]; + SHA256_CTX *pool; + + /* Track how many bytes have been added to pool 0. */ + if (st->pool_index == 0 && st->pool0_bytes < MIN_POOL_LEN) + st->pool0_bytes += len; + + /* Hash events into successive accumulator pools. */ + pool = &st->pool[st->pool_index]; + st->pool_index = (st->pool_index + 1) % NUM_POOLS; + + /* + * Fortuna specifies that events are encoded with a source identifier byte, + * a length byte, and the event data itself. We do not have source + * identifiers and they're not really important, so just encode the + * length in two bytes instead. + */ + store_16_be(len, lenbuf); + shad256_update(pool, lenbuf, 2); + shad256_update(pool, data, len); +} + +/* Limit dependencies for test program. */ +#ifndef TEST + +/* Return true if RESEED_INTERVAL microseconds have passed since the last + * reseed. */ +static krb5_boolean +enough_time_passed(struct fortuna_state *st) +{ + struct timeval tv, *last = &st->last_reseed_time; + krb5_boolean ok = FALSE; + + gettimeofday(&tv, NULL); + + /* Check how much time has passed. */ + if (tv.tv_sec > last->tv_sec + 1) + ok = TRUE; + else if (tv.tv_sec == last->tv_sec + 1) { + if (1000000 + tv.tv_usec - last->tv_usec >= RESEED_INTERVAL) + ok = TRUE; + } else if (tv.tv_usec - last->tv_usec >= RESEED_INTERVAL) + ok = TRUE; + + /* Update last_reseed_time if we're returning success. */ + if (ok) + memcpy(last, &tv, sizeof(tv)); + + return ok; +} + +static void +accumulator_output(struct fortuna_state *st, unsigned char *dst, size_t len) +{ + /* Reseed the generator with data from pools if we have accumulated enough + * data and enough time has passed since the last accumulator reseed. */ + if (st->pool0_bytes >= MIN_POOL_LEN && enough_time_passed(st)) + accumulator_reseed(st); + + generator_output(st, dst, len); +} + +static k5_mutex_t fortuna_lock = K5_MUTEX_PARTIAL_INITIALIZER; +static struct fortuna_state main_state; +#ifdef _WIN32 +static DWORD last_pid; +#else +static pid_t last_pid; +#endif +static krb5_boolean have_entropy = FALSE; + +int +k5_prng_init(void) +{ + krb5_error_code ret = 0; + unsigned char osbuf[64]; + + ret = k5_mutex_finish_init(&fortuna_lock); + if (ret) + return ret; + + init_state(&main_state); +#ifdef _WIN32 + last_pid = GetCurrentProcessId(); +#else + last_pid = getpid(); +#endif + if (k5_get_os_entropy(osbuf, sizeof(osbuf), 0)) { + generator_reseed(&main_state, osbuf, sizeof(osbuf)); + have_entropy = TRUE; + } + + return 0; +} + +void +k5_prng_cleanup(void) +{ + have_entropy = FALSE; + zap(&main_state, sizeof(main_state)); + k5_mutex_destroy(&fortuna_lock); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_random_add_entropy(krb5_context context, unsigned int randsource, + const krb5_data *indata) +{ + krb5_error_code ret; + + ret = krb5int_crypto_init(); + if (ret) + return ret; + k5_mutex_lock(&fortuna_lock); + if (randsource == KRB5_C_RANDSOURCE_OSRAND || + randsource == KRB5_C_RANDSOURCE_TRUSTEDPARTY) { + /* These sources contain enough entropy that we should use them + * immediately, so that they benefit the next request. */ + generator_reseed(&main_state, (unsigned char *)indata->data, + indata->length); + have_entropy = TRUE; + } else { + /* Other sources should just go into the pools and be used according to + * the accumulator logic. */ + accumulator_add_event(&main_state, (unsigned char *)indata->data, + indata->length); + } + k5_mutex_unlock(&fortuna_lock); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_random_make_octets(krb5_context context, krb5_data *outdata) +{ +#ifdef _WIN32 + DWORD pid = GetCurrentProcessId(); +#else + pid_t pid = getpid(); +#endif + unsigned char pidbuf[4]; + + k5_mutex_lock(&fortuna_lock); + + if (!have_entropy) { + k5_mutex_unlock(&fortuna_lock); + if (context != NULL) { + k5_set_error(&context->err, KRB5_CRYPTO_INTERNAL, + _("Random number generator could not be seeded")); + } + return KRB5_CRYPTO_INTERNAL; + } + + if (pid != last_pid) { + /* We forked; make sure child's PRNG stream differs from parent's. */ + store_32_be(pid, pidbuf); + generator_reseed(&main_state, pidbuf, 4); + last_pid = pid; + } + + accumulator_output(&main_state, (unsigned char *)outdata->data, + outdata->length); + k5_mutex_unlock(&fortuna_lock); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_random_os_entropy(krb5_context context, int strong, int *success) +{ + krb5_error_code ret; + krb5_data data; + uint8_t buf[64]; + int status = 0; + + if (!k5_get_os_entropy(buf, sizeof(buf), strong)) + goto done; + + data = make_data(buf, sizeof(buf)); + ret = krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_OSRAND, &data); + if (ret) + goto done; + + status = 1; + +done: + if (success != NULL) + *success = status; + return 0; +} + +#endif /* not TEST */ diff --git a/src/lib/crypto/krb/prng_os.c b/src/lib/crypto/krb/prng_os.c new file mode 100644 index 000000000000..8ea13e7fc1dd --- /dev/null +++ b/src/lib/crypto/krb/prng_os.c @@ -0,0 +1,72 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prng_os.c - OS PRNG implementation */ +/* + * Copyright (C) 2016 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file implements a PRNG module which relies on the system's PRNG. An + * OS packager can select this module given sufficient confidence in the + * operating system's native PRNG quality. + */ + +#include "crypto_int.h" + +int +k5_prng_init(void) +{ + return 0; +} + +void +k5_prng_cleanup(void) +{ +} + +krb5_error_code KRB5_CALLCONV +krb5_c_random_add_entropy(krb5_context context, unsigned int randsource, + const krb5_data *indata) +{ + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_random_make_octets(krb5_context context, krb5_data *outdata) +{ + krb5_boolean res; + + res = k5_get_os_entropy((uint8_t *)outdata->data, outdata->length, 0); + return res ? 0 : KRB5_CRYPTO_INTERNAL; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_random_os_entropy(krb5_context context, int strong, int *success) +{ + return 0; +} diff --git a/src/lib/crypto/krb/random_to_key.c b/src/lib/crypto/krb/random_to_key.c new file mode 100644 index 000000000000..1574625268c9 --- /dev/null +++ b/src/lib/crypto/krb/random_to_key.c @@ -0,0 +1,118 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (c) 2006 + * The Regents of the University of Michigan + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +/* + * Create a key given random data. It is assumed that random_key has + * already been initialized and random_key->contents have been allocated + * with the correct length. + */ +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_random_to_key(krb5_context context, krb5_enctype enctype, + krb5_data *random_data, krb5_keyblock *random_key) +{ + krb5_error_code ret; + const struct krb5_keytypes *ktp; + + if (random_data == NULL || random_key == NULL || + random_key->contents == NULL) + return EINVAL; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + if (random_key->length != ktp->enc->keylength) + return KRB5_BAD_KEYSIZE; + + ret = ktp->rand2key(random_data, random_key); + if (ret) + zap(random_key->contents, random_key->length); + + return ret; +} + +krb5_error_code +k5_rand2key_direct(const krb5_data *randombits, krb5_keyblock *keyblock) +{ + if (randombits->length != keyblock->length) + return KRB5_CRYPTO_INTERNAL; + + keyblock->magic = KV5M_KEYBLOCK; + memcpy(keyblock->contents, randombits->data, randombits->length); + return 0; +} + +static inline void +eighth_byte(unsigned char *b) +{ + b[7] = (((b[0] & 1) << 1) | ((b[1] & 1) << 2) | ((b[2] & 1) << 3) | + ((b[3] & 1) << 4) | ((b[4] & 1) << 5) | ((b[5] & 1) << 6) | + ((b[6] & 1) << 7)); +} + +krb5_error_code +k5_rand2key_des(const krb5_data *randombits, krb5_keyblock *keyblock) +{ + if (randombits->length != 7) + return(KRB5_CRYPTO_INTERNAL); + + keyblock->magic = KV5M_KEYBLOCK; + + /* Take the seven bytes, move them around into the top 7 bits of the + * 8 key bytes, then compute the parity bits. */ + memcpy(keyblock->contents, randombits->data, randombits->length); + eighth_byte(keyblock->contents); + k5_des_fixup_key_parity(keyblock->contents); + + return 0; +} + +krb5_error_code +k5_rand2key_des3(const krb5_data *randombits, krb5_keyblock *keyblock) +{ + int i; + + if (randombits->length != 21) + return KRB5_CRYPTO_INTERNAL; + + keyblock->magic = KV5M_KEYBLOCK; + + /* Take the seven bytes, move them around into the top 7 bits of the + * 8 key bytes, then compute the parity bits. Do this three times. */ + for (i = 0; i < 3; i++) { + memcpy(&keyblock->contents[i * 8], &randombits->data[i * 7], 7); + eighth_byte(&keyblock->contents[i * 8]); + k5_des_fixup_key_parity(&keyblock->contents[i * 8]); + } + return 0; +} diff --git a/src/lib/crypto/krb/s2k_des.c b/src/lib/crypto/krb/s2k_des.c new file mode 100644 index 000000000000..31a613bebc61 --- /dev/null +++ b/src/lib/crypto/krb/s2k_des.c @@ -0,0 +1,691 @@ +/* -*- 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. + */ + +/* + * RFC 3961 and AFS string to key. These are not standard crypto primitives + * (RFC 3961 string-to-key is implemented in OpenSSL for historical reasons but + * it doesn't get weak keys right), so we have to implement them here. + */ + +#include <ctype.h> +#include "crypto_int.h" + +#undef min +#define min(a,b) ((a)>(b)?(b):(a)) + +/* Compute a CBC checksum of in (with length len) using the specified key and + * ivec. The result is written into out. */ +static krb5_error_code +des_cbc_mac(const unsigned char *keybits, const unsigned char *ivec, + const unsigned char *in, size_t len, unsigned char *out) +{ + krb5_error_code ret; + krb5_keyblock kb; + krb5_key key; + krb5_crypto_iov iov[2]; + unsigned char zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + krb5_data outd, ivecd; + + /* Make a key from keybits. */ + kb.magic = KV5M_KEYBLOCK; + kb.enctype = ENCTYPE_DES_CBC_CRC; + kb.length = 8; + kb.contents = (unsigned char *)keybits; + ret = krb5_k_create_key(NULL, &kb, &key); + if (ret) + return ret; + + /* Make iovs for the input data, padding it out to the block size. */ + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = make_data((unsigned char *)in, len); + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = make_data(zero, krb5_roundup(len, 8) - len); + + /* Make krb5_data structures for the ivec and output. */ + ivecd = make_data((unsigned char *)ivec, 8); + outd = make_data(out, 8); + + /* Call the cbc_mac operation of the module's DES enc-provider. */ + ret = krb5int_enc_des.cbc_mac(key, iov, 2, &ivecd, &outd); + krb5_k_free_key(NULL, key); + return ret; +} + +/*** AFS string-to-key constants ***/ + +/* Initial permutation */ +static const char IP[] = { + 58,50,42,34,26,18,10, 2, + 60,52,44,36,28,20,12, 4, + 62,54,46,38,30,22,14, 6, + 64,56,48,40,32,24,16, 8, + 57,49,41,33,25,17, 9, 1, + 59,51,43,35,27,19,11, 3, + 61,53,45,37,29,21,13, 5, + 63,55,47,39,31,23,15, 7, +}; + +/* Final permutation, FP = IP^(-1) */ +static const char FP[] = { + 40, 8,48,16,56,24,64,32, + 39, 7,47,15,55,23,63,31, + 38, 6,46,14,54,22,62,30, + 37, 5,45,13,53,21,61,29, + 36, 4,44,12,52,20,60,28, + 35, 3,43,11,51,19,59,27, + 34, 2,42,10,50,18,58,26, + 33, 1,41, 9,49,17,57,25, +}; + +/* + * Permuted-choice 1 from the key bits to yield C and D. + * Note that bits 8,16... are left out: They are intended for a parity check. + */ +static const char PC1_C[] = { + 57,49,41,33,25,17, 9, + 1,58,50,42,34,26,18, + 10, 2,59,51,43,35,27, + 19,11, 3,60,52,44,36, +}; + +static const char PC1_D[] = { + 63,55,47,39,31,23,15, + 7,62,54,46,38,30,22, + 14, 6,61,53,45,37,29, + 21,13, 5,28,20,12, 4, +}; + +/* Sequence of shifts used for the key schedule */ +static const char shifts[] = { + 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1, +}; + +/* Permuted-choice 2, to pick out the bits from the CD array that generate the + * key schedule */ +static const char PC2_C[] = { + 14,17,11,24, 1, 5, + 3,28,15, 6,21,10, + 23,19,12, 4,26, 8, + 16, 7,27,20,13, 2, +}; + +static const char PC2_D[] = { + 41,52,31,37,47,55, + 30,40,51,45,33,48, + 44,49,39,56,34,53, + 46,42,50,36,29,32, +}; + +/* The E bit-selection table */ +static const char e[] = { + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9,10,11,12,13, + 12,13,14,15,16,17, + 16,17,18,19,20,21, + 20,21,22,23,24,25, + 24,25,26,27,28,29, + 28,29,30,31,32, 1, +}; + +/* P is a permutation on the selected combination of the current L and key. */ +static const char P[] = { + 16, 7,20,21, + 29,12,28,17, + 1,15,23,26, + 5,18,31,10, + 2, 8,24,14, + 32,27, 3, 9, + 19,13,30, 6, + 22,11, 4,25, +}; + +/* + * The 8 selection functions. + * For some reason, they give a 0-origin + * index, unlike everything else. + */ +static const char S[8][64] = { + {14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7, + 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8, + 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0, + 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13}, + + {15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10, + 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5, + 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15, + 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9}, + + {10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1, + 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7, + 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12}, + + { 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15, + 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9, + 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4, + 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14}, + + { 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9, + 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6, + 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14, + 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3}, + + {12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11, + 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8, + 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6, + 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13}, + + { 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1, + 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6, + 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2, + 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12}, + + {13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7, + 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2, + 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8, + 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11}, +}; + + +/* Set up the key schedule from the key. */ +static void +afs_crypt_setkey(char *key, char *E, char (*KS)[48]) +{ + int i, j, k, t; + char C[28], D[28]; /* Used to calculate key schedule. */ + + /* + * First, generate C and D by permuting + * the key. The low order bit of each + * 8-bit char is not used, so C and D are only 28 + * bits apiece. + */ + for (i = 0; i < 28; i++) { + C[i] = key[PC1_C[i] - 1]; + D[i] = key[PC1_D[i] - 1]; + } + /* + * To generate Ki, rotate C and D according + * to schedule and pick up a permutation + * using PC2. + */ + for (i = 0; i < 16; i++) { + /* Rotate. */ + for (k = 0; k < shifts[i]; k++) { + t = C[0]; + for (j = 0; j < 28 - 1; j++) + C[j] = C[j + 1]; + C[27] = t; + t = D[0]; + for (j = 0; j < 28 - 1; j++) + D[j] = D[j + 1]; + D[27] = t; + } + /* Get Ki. Note C and D are concatenated. */ + for (j = 0; j < 24; j++) { + KS[i][j] = C[PC2_C[j]-1]; + KS[i][j+24] = D[PC2_D[j]-28-1]; + } + } + + memcpy(E, e, 48); +} + +/* + * The payoff: encrypt a block. + */ + +static void +afs_encrypt_block(char *block, char *E, char (*KS)[48]) +{ + const long edflag = 0; + int i, ii; + int t, j, k; + char tempL[32]; + char f[32]; + char L[64]; /* Current block divided into two halves */ + char *const R = &L[32]; + /* The combination of the key and the input, before selection. */ + char preS[48]; + + /* First, permute the bits in the input. */ + for (j = 0; j < 64; j++) + L[j] = block[IP[j] - 1]; + /* Perform an encryption operation 16 times. */ + for (ii = 0; ii < 16; ii++) { + /* Set direction. */ + i = (edflag) ? 15 - ii : ii; + /* Save the R array, which will be the new L. */ + memcpy(tempL, R, 32); + /* Expand R to 48 bits using the E selector; exclusive-or with the + * current key bits. */ + for (j = 0; j < 48; j++) + preS[j] = R[E[j] - 1] ^ KS[i][j]; + /* + * The pre-select bits are now considered in 8 groups of 6 bits each. + * The 8 selection functions map these 6-bit quantities into 4-bit + * quantities and the results permuted to make an f(R, K). The + * indexing into the selection functions is peculiar; it could be + * simplified by rewriting the tables. + */ + for (j = 0; j < 8; j++) { + t = 6 * j; + k = S[j][(preS[t + 0] << 5) + + (preS[t + 1] << 3) + + (preS[t + 2] << 2) + + (preS[t + 3] << 1) + + (preS[t + 4] << 0) + + (preS[t + 5] << 4)]; + t = 4 * j; + f[t + 0] = (k >> 3) & 1; + f[t + 1] = (k >> 2) & 1; + f[t + 2] = (k >> 1) & 1; + f[t + 3] = (k >> 0) & 1; + } + /* The new R is L ^ f(R, K). The f here has to be permuted first, + * though. */ + for (j = 0; j < 32; j++) + R[j] = L[j] ^ f[P[j] - 1]; + /* Finally, the new L (the original R) is copied back. */ + memcpy(L, tempL, 32); + } + /* The output L and R are reversed. */ + for (j = 0; j < 32; j++) { + t = L[j]; + L[j] = R[j]; + R[j] = t; + } + /* The final output gets the inverse permutation of the very original. */ + for (j = 0; j < 64; j++) + block[j] = L[FP[j] - 1]; +} + +/* iobuf must be at least 16 bytes */ +static char * +afs_crypt(const char *pw, const char *salt, char *iobuf) +{ + int i, j, c; + int temp; + char block[66]; + char E[48]; + char KS[16][48]; /* Key schedule, generated from key */ + + for (i = 0; i < 66; i++) + block[i] = 0; + for (i = 0; (c = *pw) != '\0' && i < 64; pw++){ + for(j = 0; j < 7; j++, i++) + block[i] = (c >> (6 - j)) & 01; + i++; + } + + afs_crypt_setkey(block, E, KS); + + for (i = 0; i < 66; i++) + block[i] = 0; + + for (i = 0; i < 2; i++) { + c = *salt++; + iobuf[i] = c; + if (c > 'Z') + c -= 6; + if (c > '9') + c -= 7; + c -= '.'; + for (j = 0; j < 6; j++) { + if ((c >> j) & 01) { + temp = E[6 * i + j]; + E[6 * i + j] = E[6 * i + j + 24]; + E[6 * i + j + 24] = temp; + } + } + } + + for (i = 0; i < 25; i++) + afs_encrypt_block(block, E, KS); + + for (i = 0; i < 11; i++) { + c = 0; + for (j = 0; j < 6; j++) { + c <<= 1; + c |= block[6 * i + j]; + } + c += '.'; + if (c > '9') + c += 7; + if (c > 'Z') + c += 6; + iobuf[i + 2] = c; + } + iobuf[i + 2] = 0; + if (iobuf[1] == 0) + iobuf[1] = iobuf[0]; + return iobuf; +} + +static krb5_error_code +afs_s2k_oneblock(const krb5_data *data, const krb5_data *salt, + unsigned char *key_out) +{ + unsigned int i; + unsigned char password[9]; /* trailing nul for crypt() */ + char afs_crypt_buf[16]; + + /* + * Run afs_crypt and use the first eight returned bytes after the copy of + * the (fixed) salt. + * + * Since the returned bytes are alphanumeric, the output is limited to + * 2**48 possibilities; for each byte, only 64 possible values can be used. + */ + + memset(password, 0, sizeof(password)); + if (salt->length > 0) + memcpy(password, salt->data, min(salt->length, 8)); + for (i = 0; i < 8; i++) { + if (isupper(password[i])) + password[i] = tolower(password[i]); + } + for (i = 0; i < data->length; i++) + password[i] ^= data->data[i]; + for (i = 0; i < 8; i++) { + if (password[i] == '\0') + password[i] = 'X'; + } + password[8] = '\0'; + /* Out-of-bounds salt characters are equivalent to a salt string + * of "p1". */ + strncpy((char *)key_out, + (char *)afs_crypt((char *)password, "#~", afs_crypt_buf) + 2, 8); + for (i = 0; i < 8; i++) + key_out[i] <<= 1; + /* Fix up key parity again. */ + k5_des_fixup_key_parity(key_out); + zap(password, sizeof(password)); + return 0; +} + +static krb5_error_code +afs_s2k_multiblock(const krb5_data *data, const krb5_data *salt, + unsigned char *key_out) +{ + krb5_error_code ret; + unsigned char ivec[8], tkey[8], *password; + size_t pw_len = salt->length + data->length; + unsigned int i, j; + + /* Do a CBC checksum, twice, and use the result as the new key. */ + + password = malloc(pw_len); + if (!password) + return ENOMEM; + + if (data->length > 0) + memcpy(password, data->data, data->length); + for (i = data->length, j = 0; j < salt->length; i++, j++) { + password[i] = salt->data[j]; + if (isupper(password[i])) + password[i] = tolower(password[i]); + } + + memcpy(ivec, "kerberos", sizeof(ivec)); + memcpy(tkey, ivec, sizeof(tkey)); + k5_des_fixup_key_parity(tkey); + ret = des_cbc_mac(tkey, ivec, password, pw_len, tkey); + if (ret) + goto cleanup; + + memcpy(ivec, tkey, sizeof(ivec)); + k5_des_fixup_key_parity(tkey); + ret = des_cbc_mac(tkey, ivec, password, pw_len, key_out); + if (ret) + goto cleanup; + k5_des_fixup_key_parity(key_out); + +cleanup: + zapfree(password, pw_len); + return ret; +} + +static krb5_error_code +afs_s2k(const krb5_data *data, const krb5_data *salt, unsigned char *key_out) +{ + if (data->length <= 8) + return afs_s2k_oneblock(data, salt, key_out); + else + return afs_s2k_multiblock(data, salt, key_out); +} + +static krb5_error_code +des_s2k(const krb5_data *pw, const krb5_data *salt, unsigned char *key_out) +{ + union { + /* 8 "forward" bytes, 8 "reverse" bytes */ + unsigned char uc[16]; + krb5_ui_4 ui[4]; + } temp; + unsigned int i; + krb5_ui_4 x, y, z; + unsigned char *p, *copy; + size_t copylen; + krb5_error_code ret; + + /* As long as the architecture is big-endian or little-endian, it + doesn't matter which it is. Think of it as reversing the + bytes, and also reversing the bits within each byte. But this + current algorithm is dependent on having four 8-bit char values + exactly overlay a 32-bit integral type. */ + if (sizeof(temp.uc) != sizeof(temp.ui) + || (unsigned char)~0 != 0xFF + || (krb5_ui_4)~(krb5_ui_4)0 != 0xFFFFFFFF + || (temp.uc[0] = 1, temp.uc[1] = 2, temp.uc[2] = 3, temp.uc[3] = 4, + !(temp.ui[0] == 0x01020304 + || temp.ui[0] == 0x04030201))) + abort(); +#define FETCH4(VAR, IDX) VAR = temp.ui[IDX/4] +#define PUT4(VAR, IDX) temp.ui[IDX/4] = VAR + + copylen = pw->length + (salt ? salt->length : 0); + /* Don't need NUL termination, at this point we're treating it as + a byte array, not a string. */ + copy = malloc(copylen); + if (copy == NULL) + return ENOMEM; + if (pw->length > 0) + memcpy(copy, pw->data, pw->length); + if (salt != NULL && salt->length > 0) + memcpy(copy + pw->length, salt->data, salt->length); + + memset(&temp, 0, sizeof(temp)); + p = temp.uc; + /* Handle the fan-fold xor operation by splitting the data into + forward and reverse sections, and combine them later, rather + than having to do the reversal over and over again. */ + for (i = 0; i < copylen; i++) { + *p++ ^= copy[i]; + if (p == temp.uc+16) { + p = temp.uc; +#ifdef PRINT_TEST_VECTORS + { + int j; + printf("after %d input bytes:\nforward block:\t", i+1); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\nreverse block:\t"); + for (j = 8; j < 16; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif + } + } + +#ifdef PRINT_TEST_VECTORS + if (p != temp.uc) { + int j; + printf("at end, after %d input bytes:\nforward block:\t", i); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\nreverse block:\t"); + for (j = 8; j < 16; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif +#define REVERSE(VAR) \ + { \ + krb5_ui_4 old = VAR, temp1 = 0; \ + int j; \ + for (j = 0; j < 32; j++) { \ + temp1 = (temp1 << 1) | (old & 1); \ + old >>= 1; \ + } \ + VAR = temp1; \ + } + + FETCH4 (x, 8); + FETCH4 (y, 12); + /* Ignore high bits of each input byte. */ + x &= 0x7F7F7F7F; + y &= 0x7F7F7F7F; + /* Reverse the bit strings -- after this, y is "before" x. */ + REVERSE (x); + REVERSE (y); +#ifdef PRINT_TEST_VECTORS + { + int j; + union { unsigned char uc[4]; krb5_ui_4 ui; } t2; + printf("after reversal, reversed block:\n\t\t"); + t2.ui = y; + for (j = 0; j < 4; j++) + printf(" %02x", t2.uc[j] & 0xff); + t2.ui = x; + for (j = 0; j < 4; j++) + printf(" %02x", t2.uc[j] & 0xff); + printf("\n"); + } +#endif + /* Ignored bits are now at the bottom of each byte, where we'll + * put the parity bits. Good. */ + FETCH4 (z, 0); + z &= 0x7F7F7F7F; + /* Ignored bits for z are at the top of each byte; fix that. */ + z <<= 1; + /* Finish the fan-fold xor for these four bytes. */ + z ^= y; + PUT4 (z, 0); + /* Now do the second four bytes. */ + FETCH4 (z, 4); + z &= 0x7F7F7F7F; + /* Ignored bits for z are at the top of each byte; fix that. */ + z <<= 1; + /* Finish the fan-fold xor for these four bytes. */ + z ^= x; + PUT4 (z, 4); + +#ifdef PRINT_TEST_VECTORS + { + int j; + printf("after reversal, combined block:\n\t\t"); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif + +#define FIXUP(k) (k5_des_fixup_key_parity(k), \ + k5_des_is_weak_key(k) ? (k[7] ^= 0xF0) : 0) + + /* Now temp.cb is the temporary key, with invalid parity. */ + FIXUP(temp.uc); + +#ifdef PRINT_TEST_VECTORS + { + int j; + printf("after fixing parity and weak keys:\n\t\t"); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif + + ret = des_cbc_mac(temp.uc, temp.uc, copy, copylen, temp.uc); + if (ret) + goto cleanup; + +#ifdef PRINT_TEST_VECTORS + { + int j; + printf("cbc checksum:\n\t\t"); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif + + FIXUP(temp.uc); + +#ifdef PRINT_TEST_VECTORS + { + int j; + printf("after fixing parity and weak keys:\n\t\t"); + for (j = 0; j < 8; j++) + printf(" %02x", temp.uc[j] & 0xff); + printf("\n"); + } +#endif + + memcpy(key_out, temp.uc, 8); + +cleanup: + zap(&temp, sizeof(temp)); + zapfree(copy, copylen); + return ret; +} + +krb5_error_code +krb5int_des_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, const krb5_data *salt, + const krb5_data *parm, krb5_keyblock *keyblock) +{ + int type; + + if (parm != NULL) { + if (parm->length != 1) + return KRB5_ERR_BAD_S2K_PARAMS; + type = parm->data[0]; + if (type != 0 && type != 1) + return KRB5_ERR_BAD_S2K_PARAMS; + } else + type = 0; + + /* Use AFS string to key if we were told to. */ + if (type == 1) + return afs_s2k(string, salt, keyblock->contents); + + return des_s2k(string, salt, keyblock->contents); +} diff --git a/src/lib/crypto/krb/s2k_pbkdf2.c b/src/lib/crypto/krb/s2k_pbkdf2.c new file mode 100644 index 000000000000..ec5856c2be79 --- /dev/null +++ b/src/lib/crypto/krb/s2k_pbkdf2.c @@ -0,0 +1,216 @@ +/* -*- 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 "crypto_int.h" + +static const unsigned char kerberos[] = "kerberos"; +#define kerberos_len (sizeof(kerberos)-1) + +krb5_error_code +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) +{ + krb5_error_code ret; + size_t keybytes, keylength, concatlen; + unsigned char *concat = NULL, *foldstring = NULL, *foldkeydata = NULL; + krb5_data indata; + krb5_keyblock foldkeyblock; + krb5_key foldkey = NULL; + + /* keyblock->length is checked by krb5int_derive_key. */ + + keybytes = ktp->enc->keybytes; + keylength = ktp->enc->keylength; + + concatlen = string->length + (salt ? salt->length : 0); + + concat = k5alloc(concatlen, &ret); + if (ret != 0) + goto cleanup; + foldstring = k5alloc(keybytes, &ret); + if (ret != 0) + goto cleanup; + foldkeydata = k5alloc(keylength, &ret); + if (ret != 0) + goto cleanup; + + /* construct input string ( = string + salt), fold it, make_key it */ + + if (string->length > 0) + memcpy(concat, string->data, string->length); + if (salt != NULL && salt->length > 0) + memcpy(concat + string->length, salt->data, salt->length); + + krb5int_nfold(concatlen*8, concat, keybytes*8, foldstring); + + indata.length = keybytes; + indata.data = (char *) foldstring; + foldkeyblock.length = keylength; + foldkeyblock.contents = foldkeydata; + foldkeyblock.enctype = ktp->etype; + + ret = ktp->rand2key(&indata, &foldkeyblock); + if (ret != 0) + goto cleanup; + + ret = krb5_k_create_key(NULL, &foldkeyblock, &foldkey); + if (ret != 0) + goto cleanup; + + /* now derive the key from this one */ + + indata.length = kerberos_len; + indata.data = (char *) kerberos; + + ret = krb5int_derive_keyblock(ktp->enc, NULL, foldkey, keyblock, &indata, + DERIVE_RFC3961); + if (ret != 0) + memset(keyblock->contents, 0, keyblock->length); + +cleanup: + zapfree(concat, concatlen); + zapfree(foldstring, keybytes); + zapfree(foldkeydata, keylength); + krb5_k_free_key(NULL, foldkey); + return ret; +} + + +#define MAX_ITERATION_COUNT 0x1000000L + +krb5_boolean k5_allow_weak_pbkdf2iter = FALSE; + +static krb5_error_code +pbkdf2_string_to_key(const struct krb5_keytypes *ktp, const krb5_data *string, + const krb5_data *salt, const krb5_data *pepper, + const krb5_data *params, krb5_keyblock *key, + enum deriv_alg deriv_alg, unsigned long def_iter_count) +{ + const struct krb5_hash_provider *hash; + unsigned long iter_count; + krb5_data out; + static const krb5_data usage = { KV5M_DATA, 8, "kerberos" }; + krb5_key tempkey = NULL; + krb5_error_code err; + krb5_data sandp = empty_data(); + + if (params) { + unsigned char *p = (unsigned char *) params->data; + if (params->length != 4) + return KRB5_ERR_BAD_S2K_PARAMS; + iter_count = load_32_be(p); + /* Zero means 2^32, which is way above what we will accept. Also don't + * accept values less than the default, unless we're running tests. */ + if (iter_count == 0 || + (!k5_allow_weak_pbkdf2iter && iter_count < def_iter_count)) + return KRB5_ERR_BAD_S2K_PARAMS; + + } else + iter_count = def_iter_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; + + if (pepper != NULL) { + err = alloc_data(&sandp, pepper->length + 1 + salt->length); + if (err) + return err; + + if (pepper->length > 0) + memcpy(sandp.data, pepper->data, pepper->length); + sandp.data[pepper->length] = '\0'; + if (salt->length > 0) + memcpy(&sandp.data[pepper->length + 1], salt->data, salt->length); + + salt = &sandp; + } + + hash = (ktp->hash != NULL) ? ktp->hash : &krb5int_hash_sha1; + err = krb5int_pbkdf2_hmac(hash, &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, ktp->hash, tempkey, key, &usage, + deriv_alg); + +cleanup: + if (sandp.data) + free(sandp.data); + if (err) + memset (out.data, 0, out.length); + krb5_k_free_key (NULL, tempkey); + return err; +} + +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) +{ + return pbkdf2_string_to_key(ktp, string, salt, NULL, params, key, + DERIVE_RFC3961, 4096); +} + +krb5_error_code +krb5int_camellia_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key) +{ + krb5_data pepper = string2data(ktp->name); + + return pbkdf2_string_to_key(ktp, string, salt, &pepper, params, key, + DERIVE_SP800_108_CMAC, 32768); +} + +krb5_error_code +krb5int_aes2_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, const krb5_data *salt, + const krb5_data *params, krb5_keyblock *key) +{ + krb5_data pepper = string2data(ktp->name); + + return pbkdf2_string_to_key(ktp, string, salt, &pepper, params, key, + DERIVE_SP800_108_HMAC, 32768); +} diff --git a/src/lib/crypto/krb/s2k_rc4.c b/src/lib/crypto/krb/s2k_rc4.c new file mode 100644 index 000000000000..49ad89d323b0 --- /dev/null +++ b/src/lib/crypto/krb/s2k_rc4.c @@ -0,0 +1,37 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include "crypto_int.h" +#include "k5-utf8.h" + +krb5_error_code +krb5int_arcfour_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, const krb5_data *salt, + const krb5_data *params, krb5_keyblock *key) +{ + krb5_error_code err = 0; + krb5_crypto_iov iov; + krb5_data hash_out; + unsigned char *copystr; + size_t copystrlen; + + if (params != NULL) + return KRB5_ERR_BAD_S2K_PARAMS; + + if (key->length != 16) + return (KRB5_BAD_MSIZE); + + /* We ignore salt per the Microsoft spec. */ + err = krb5int_utf8cs_to_ucs2les(string->data, string->length, ©str, + ©strlen); + if (err) + return err; + + /* the actual MD4 hash of the data */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data(copystr, copystrlen); + hash_out = make_data(key->contents, key->length); + err = krb5int_hash_md4.hash(&iov, 1, &hash_out); + + /* Zero out the data behind us */ + zapfree(copystr, copystrlen); + return err; +} diff --git a/src/lib/crypto/krb/state.c b/src/lib/crypto/krb/state.c new file mode 100644 index 000000000000..a7fb020b2f6d --- /dev/null +++ b/src/lib/crypto/krb/state.c @@ -0,0 +1,60 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/state.c */ +/* + * Copyright (C) 2001 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 + + * + * + * + * * Section 6 (Encryption) of the Kerberos revisions document defines + * cipher states to be used to chain encryptions and decryptions + * together. Examples of cipher states include initialization vectors + * for CBC encription. This file contains implementations of + * krb5_c_init_state and krb5_c_free_state used by clients of the + * Kerberos crypto library. + */ +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_init_state (krb5_context context, const krb5_keyblock *key, + krb5_keyusage keyusage, krb5_data *new_state) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(key->enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + return ktp->enc->init_state(key, keyusage, new_state); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_free_state(krb5_context context, const krb5_keyblock *key, + krb5_data *state) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(key->enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + ktp->enc->free_state(state); + return 0; +} diff --git a/src/lib/crypto/krb/string_to_cksumtype.c b/src/lib/crypto/krb/string_to_cksumtype.c new file mode 100644 index 000000000000..3498d2a0539d --- /dev/null +++ b/src/lib/crypto/krb/string_to_cksumtype.c @@ -0,0 +1,56 @@ +/* -*- 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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_string_to_cksumtype(char *string, krb5_cksumtype *cksumtypep) +{ + unsigned int i, j; + const char *alias; + const struct krb5_cksumtypes *ctp; + + for (i=0; i<krb5int_cksumtypes_length; i++) { + ctp = &krb5int_cksumtypes_list[i]; + if (strcasecmp(ctp->name, string) == 0) { + *cksumtypep = ctp->ctype; + return 0; + } +#define MAX_ALIASES (sizeof(ctp->aliases) / sizeof(ctp->aliases[0])) + for (j = 0; j < MAX_ALIASES; j++) { + alias = ctp->aliases[j]; + if (alias == NULL) + break; + if (strcasecmp(alias, string) == 0) { + *cksumtypep = ctp->ctype; + return 0; + } + } + } + + return EINVAL; +} diff --git a/src/lib/crypto/krb/string_to_key.c b/src/lib/crypto/krb/string_to_key.c new file mode 100644 index 000000000000..b55ee75d2f34 --- /dev/null +++ b/src/lib/crypto/krb/string_to_key.c @@ -0,0 +1,74 @@ +/* -*- 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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_string_to_key(krb5_context context, krb5_enctype enctype, + const krb5_data *string, const krb5_data *salt, + krb5_keyblock *key) +{ + return krb5_c_string_to_key_with_params(context, enctype, string, salt, + NULL, key); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, krb5_keyblock *key) +{ + krb5_error_code ret; + const struct krb5_keytypes *ktp; + size_t keylength; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + keylength = ktp->enc->keylength; + + /* Fail gracefully if someone is using the old AFS string-to-key hack. */ + if (salt != NULL && salt->length == SALT_TYPE_AFS_LENGTH) + return EINVAL; + + key->contents = malloc(keylength); + if (key->contents == NULL) + return ENOMEM; + + key->magic = KV5M_KEYBLOCK; + key->enctype = enctype; + key->length = keylength; + + ret = (*ktp->str2key)(ktp, string, salt, params, key); + if (ret) { + zapfree(key->contents, keylength); + key->length = 0; + key->contents = NULL; + } + + return ret; +} diff --git a/src/lib/crypto/krb/t_fortuna.c b/src/lib/crypto/krb/t_fortuna.c new file mode 100644 index 000000000000..4f25bee62cb5 --- /dev/null +++ b/src/lib/crypto/krb/t_fortuna.c @@ -0,0 +1,179 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/t_fortuna.c - Fortuna test program */ +/* + * Copyright (c) 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (C) 2011 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" +#ifdef FORTUNA + +/* Include most of prng_fortuna.c so we can test the PRNG internals. */ +#define TEST +#include "prng_fortuna.c" + +static void +display(const unsigned char *data, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + printf("%02X", data[i]); + printf("\n"); +} + +/* + * Generate data from st with its current internal state and check for + * significant bias in each bit of the resulting bytes. This test would have a + * small chance of failure on random inputs, but we have a predictable state + * after all the other tests have been run, so it will never fail if the PRNG + * operates the way we expect. + */ +static void +head_tail_test(struct fortuna_state *st) +{ + static unsigned char buffer[1024 * 1024]; + unsigned char c; + size_t i, len = sizeof(buffer); + int bit, bits[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + double res; + + memset(buffer, 0, len); + + generator_output(st, buffer, len); + for (i = 0; i < len; i++) { + c = buffer[i]; + for (bit = 0; bit < 8 && c; bit++) { + if (c & 1) + bits[bit]++; + c = c >> 1; + } + } + + for (bit = 0; bit < 8; bit++) { + res = ((double)abs(len - bits[bit] * 2)) / (double)len; + if (res > 0.005){ + fprintf(stderr, + "Bit %d: %d zero, %d one exceeds 0.5%% variance (%f)\n", + bit, (int)len - bits[bit], bits[bit], res); + exit(1); + } + } +} + +int +main(int argc, char **argv) +{ + struct fortuna_state test_state; + struct fortuna_state *st = &test_state; + static unsigned char buf[2 * 1024 * 1024]; + unsigned int i; + + /* Seed the generator with a known state. */ + init_state(&test_state); + generator_reseed(st, (unsigned char *)"test", 4); + + /* Generate two pieces of output; key should change for each request. */ + generator_output(st, buf, 32); + display(buf, 32); + generator_output(st, buf, 32); + display(buf, 32); + + /* Generate a lot of output to test key changes during request. */ + generator_output(st, buf, sizeof(buf)); + display(buf, 32); + display(buf + sizeof(buf) - 32, 32); + + /* Reseed the generator and generate more output. */ + generator_reseed(st, (unsigned char *)"retest", 6); + generator_output(st, buf, 32); + display(buf, 32); + + /* Add sample data to accumulator pools. */ + for (i = 0; i < 44; i++) { + store_32_be(i, buf); + accumulator_add_event(st, buf, 4); + } + assert(st->pool_index == 12); + assert(st->pool0_bytes == 8); + + /* Exercise accumulator reseeds. */ + accumulator_reseed(st); + generator_output(st, buf, 32); + display(buf, 32); + accumulator_reseed(st); + generator_output(st, buf, 32); + display(buf, 32); + accumulator_reseed(st); + generator_output(st, buf, 32); + display(buf, 32); + for (i = 0; i < 1000; i++) + accumulator_reseed(st); + assert(st->reseed_count == 1003); + generator_output(st, buf, 32); + display(buf, 32); + + head_tail_test(st); + return 0; +} + +#else /* FORTUNA */ + +int +main() +{ + return 0; +} + +#endif /* FORTUNA */ diff --git a/src/lib/crypto/krb/t_fortuna.expected b/src/lib/crypto/krb/t_fortuna.expected new file mode 100644 index 000000000000..2d5738c15f2d --- /dev/null +++ b/src/lib/crypto/krb/t_fortuna.expected @@ -0,0 +1,9 @@ +A7C846B4EEAF6AB78AB33FFC77197BB0364C364E5A4259593464162B14C494F1 +EDC0776CA17E4FC395823653D1956D6873A55A1829D85D8B46340F3C9DD113F2 +B551F4EDF860BEB49E89BFF9B60BFD955ED85B070E18667189450962C503CBE5 +069A4F41D88CC12927672F1039C50DD50A0713E0AD542A6CDCD1E75CC4E7FB36 +E4EBA939FB027DACF1E7406461703C57B48D8BC0A1039A170FAD5E35C088B789 +68199B6755105BC22C343BD339EA2035E7A3F9535DC83DE3436C794EABA18B34 +49AD3C22E015666A269F37CA47EEF075860CC21588F3CF8D7EB5A9DC4D59C0F4 +9EFCB204F1B588A918B6A81D1E0E25C78C0921CF4839BE38D698EE8E30097BED +66B252E879C2548A3FC3FEAF6B7ABCDBAFB1A45F5FB68EB49AB12CC13B1A091B diff --git a/src/lib/crypto/krb/valid_cksumtype.c b/src/lib/crypto/krb/valid_cksumtype.c new file mode 100644 index 000000000000..eb7807f7eda2 --- /dev/null +++ b/src/lib/crypto/krb/valid_cksumtype.c @@ -0,0 +1,39 @@ +/* -*- 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 "crypto_int.h" + +krb5_boolean KRB5_CALLCONV +krb5_c_valid_cksumtype(krb5_cksumtype ctype) +{ + const struct krb5_cksumtypes *ctp; + + ctp = find_cksumtype(ctype); + if (ctp == NULL) + return FALSE; + return TRUE; +} diff --git a/src/lib/crypto/krb/verify_checksum.c b/src/lib/crypto/krb/verify_checksum.c new file mode 100644 index 000000000000..09425ea7aa90 --- /dev/null +++ b/src/lib/crypto/krb/verify_checksum.c @@ -0,0 +1,98 @@ +/* -*- 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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_verify_checksum(krb5_context context, krb5_key key, + krb5_keyusage usage, const krb5_data *data, + const krb5_checksum *cksum, krb5_boolean *valid) +{ + const struct krb5_cksumtypes *ctp; + krb5_cksumtype cksumtype; + krb5_crypto_iov iov; + krb5_error_code ret; + krb5_data cksum_data; + krb5_checksum computed; + + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *data; + + /* A 0 checksum type means use the mandatory checksum. */ + cksumtype = cksum->checksum_type; + if (cksumtype == 0 && key != NULL) { + ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype, + &cksumtype); + if (ret) + return ret; + } + ctp = find_cksumtype(cksumtype); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + ret = verify_key(ctp, key); + if (ret != 0) + return ret; + + /* If there's actually a verify function, call it. */ + cksum_data = make_data(cksum->contents, cksum->length); + if (ctp->verify != NULL) + return ctp->verify(ctp, key, usage, &iov, 1, &cksum_data, valid); + + /* Otherwise, make the checksum again, and compare. */ + if (cksum->length != ctp->output_size) + return KRB5_BAD_MSIZE; + + ret = krb5_k_make_checksum(context, cksum->checksum_type, key, usage, + data, &computed); + if (ret) + return ret; + + *valid = (k5_bcmp(computed.contents, cksum->contents, + ctp->output_size) == 0); + + free(computed.contents); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *data, + const krb5_checksum *cksum, krb5_boolean *valid) +{ + krb5_key key = NULL; + krb5_error_code ret; + + if (keyblock != NULL) { + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + } + ret = krb5_k_verify_checksum(context, key, usage, data, cksum, valid); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/verify_checksum_iov.c b/src/lib/crypto/krb/verify_checksum_iov.c new file mode 100644 index 000000000000..fc76c0e269f4 --- /dev/null +++ b/src/lib/crypto/krb/verify_checksum_iov.c @@ -0,0 +1,101 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/verify_checksum_iov.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 "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_verify_checksum_iov(krb5_context context, + krb5_cksumtype checksum_type, + krb5_key key, + krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_boolean *valid) +{ + const struct krb5_cksumtypes *ctp; + krb5_error_code ret; + krb5_data computed; + krb5_crypto_iov *checksum; + + if (checksum_type == 0) { + ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype, + &checksum_type); + if (ret != 0) + return ret; + } + ctp = find_cksumtype(checksum_type); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + ret = verify_key(ctp, key); + if (ret != 0) + return ret; + + checksum = krb5int_c_locate_iov((krb5_crypto_iov *)data, num_data, + KRB5_CRYPTO_TYPE_CHECKSUM); + if (checksum == NULL || checksum->data.length != ctp->output_size) + return KRB5_BAD_MSIZE; + + /* If there's actually a verify function, call it. */ + if (ctp->verify != NULL) { + return ctp->verify(ctp, key, usage, data, num_data, &checksum->data, + valid); + } + + ret = alloc_data(&computed, ctp->compute_size); + if (ret != 0) + return ret; + + ret = ctp->checksum(ctp, key, usage, data, num_data, &computed); + if (ret == 0) { + *valid = (k5_bcmp(computed.data, checksum->data.data, + ctp->output_size) == 0); + } + + zapfree(computed.data, ctp->compute_size); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_verify_checksum_iov(krb5_context context, + krb5_cksumtype checksum_type, + const krb5_keyblock *keyblock, + krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_boolean *valid) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_verify_checksum_iov(context, checksum_type, key, usage, data, + num_data, valid); + krb5_k_free_key(context, key); + return ret; +} |
