aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2009-10-02 15:33:56 +0000
committerGreg Hudson <ghudson@mit.edu>2009-10-02 15:33:56 +0000
commitafe943fe4d3092ce8d5e72e278997ca61833c367 (patch)
tree5fbb9be971fb618d3f83b8d2d6f2df26d4409ee5
parentcd65d24ab942f83fa90f7bb54aa190887450c1e6 (diff)
downloadkrb5-afe943fe4d3092ce8d5e72e278997ca61833c367.zip
krb5-afe943fe4d3092ce8d5e72e278997ca61833c367.tar.gz
krb5-afe943fe4d3092ce8d5e72e278997ca61833c367.tar.bz2
Merge trunk changes from r22791 to r22833 to enc-perf branch
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/enc-perf@22834 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/lib/crypto/builtin/hash_provider/Makefile.in24
-rw-r--r--src/lib/crypto/openssl/arcfour/arcfour-int.h35
-rw-r--r--src/lib/crypto/openssl/arcfour/arcfour.c326
-rw-r--r--src/lib/crypto/openssl/arcfour/arcfour.h43
-rw-r--r--src/lib/crypto/openssl/arcfour/arcfour_aead.c325
-rw-r--r--src/lib/crypto/openssl/arcfour/arcfour_s2k.c59
-rw-r--r--src/lib/crypto/openssl/des/afsstring2key.c27
-rw-r--r--src/lib/crypto/openssl/des/d3_aead.c34
-rw-r--r--src/lib/crypto/openssl/des/d3_cbc.c51
-rw-r--r--src/lib/crypto/openssl/des/d3_kysched.c18
-rw-r--r--src/lib/crypto/openssl/des/des_int.h377
-rw-r--r--src/lib/crypto/openssl/des/f_aead.c33
-rw-r--r--src/lib/crypto/openssl/des/f_cbc.c89
-rw-r--r--src/lib/crypto/openssl/des/f_cksum.c18
-rw-r--r--src/lib/crypto/openssl/des/f_parity.c29
-rw-r--r--src/lib/crypto/openssl/des/f_sched.c15
-rw-r--r--src/lib/crypto/openssl/des/f_tables.c17
-rw-r--r--src/lib/crypto/openssl/des/f_tables.h9
-rw-r--r--src/lib/crypto/openssl/des/key_sched.c18
-rw-r--r--src/lib/crypto/openssl/des/string2key.c26
-rw-r--r--src/lib/crypto/openssl/des/weak_key.c87
-rw-r--r--src/lib/crypto/openssl/enc_provider/aes.c505
-rw-r--r--src/lib/crypto/openssl/enc_provider/des.c107
-rw-r--r--src/lib/crypto/openssl/enc_provider/des3.c118
-rw-r--r--src/lib/crypto/openssl/enc_provider/rc4.c10
25 files changed, 2257 insertions, 143 deletions
diff --git a/src/lib/crypto/builtin/hash_provider/Makefile.in b/src/lib/crypto/builtin/hash_provider/Makefile.in
index 75b3d1b..a901d11 100644
--- a/src/lib/crypto/builtin/hash_provider/Makefile.in
+++ b/src/lib/crypto/builtin/hash_provider/Makefile.in
@@ -13,13 +13,23 @@ DEFS=
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
-STLIBOBJS= hash_crc32.o hash_md4.o hash_md5.o hash_sha1.o
-
-OBJS= $(OUTPRE)hash_crc32.$(OBJEXT) $(OUTPRE)hash_md4.$(OBJEXT) \
- $(OUTPRE)hash_md5.$(OBJEXT) $(OUTPRE)hash_sha1.$(OBJEXT)
-
-SRCS= $(srcdir)/hash_crc32.c $(srcdir)/hash_md4.c \
- $(srcdir)/hash_md5.c $(srcdir)/hash_sha1.c
+CIMPL = @CRYPTO_IMPL@/hash_provider
+
+STLIBOBJS= \
+ ../../$(CIMPL)/hash_crc32.o \
+ ../../$(CIMPL)/hash_md4.o \
+ ../../$(CIMPL)/hash_md5.o \
+ ../../$(CIMPL)/hash_sha1.o
+
+OBJS= $(OUTPRE)../../$(CIMPL)/hash_crc32.$(OBJEXT) \
+ $(OUTPRE)../../$(CIMPL)/hash_md4.$(OBJEXT) \
+ $(OUTPRE)../../$(CIMPL)/hash_md5.$(OBJEXT) \
+ $(OUTPRE)../../$(CIMPL)/hash_sha1.$(OBJEXT)
+
+SRCS= $(srcdir)/../../$(CIMPL)/hash_crc32.c \
+ $(srcdir)/../../$(CIMPL)/hash_md4.c \
+ $(srcdir)/../../$(CIMPL)/hash_md5.c \
+ $(srcdir)/../../$(CIMPL)/hash_sha1.c
##DOS##LIBOBJS = $(OBJS)
diff --git a/src/lib/crypto/openssl/arcfour/arcfour-int.h b/src/lib/crypto/openssl/arcfour/arcfour-int.h
new file mode 100644
index 0000000..d9db0be
--- /dev/null
+++ b/src/lib/crypto/openssl/arcfour/arcfour-int.h
@@ -0,0 +1,35 @@
+/*
+
+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)
+
+*/
+#ifndef ARCFOUR_INT_H
+#define ARCFOUR_INT_H
+
+#include "arcfour.h"
+#include <openssl/evp.h>
+
+#define CONFOUNDERLENGTH 8
+
+typedef struct
+{
+ EVP_CIPHER_CTX evp_ctx;
+ unsigned int x;
+ unsigned int y;
+ unsigned char state[256];
+
+} ArcfourContext;
+
+typedef struct {
+ int initialized;
+ ArcfourContext ctx;
+} ArcFourCipherState;
+
+krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage);
+
+extern const char *const krb5int_arcfour_l40;
+
+#endif /* ARCFOUR_INT_H */
diff --git a/src/lib/crypto/openssl/arcfour/arcfour.c b/src/lib/crypto/openssl/arcfour/arcfour.c
new file mode 100644
index 0000000..687f276
--- /dev/null
+++ b/src/lib/crypto/openssl/arcfour/arcfour.c
@@ -0,0 +1,326 @@
+/*
+
+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 "k5-int.h"
+#include "arcfour-int.h"
+#include "hash_provider/hash_provider.h"
+
+const char *const krb5int_arcfour_l40 = "fortybits";
+
+void
+krb5_arcfour_encrypt_length(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ size_t inputlen, size_t *length)
+{
+ size_t blocksize, hashsize;
+
+ blocksize = enc->block_size;
+ hashsize = hash->hashsize;
+
+ /* checksum + (confounder + inputlen, in even blocksize) */
+ *length = hashsize + krb5_roundup(8 + inputlen, blocksize);
+}
+
+ krb5_keyusage
+ krb5int_arcfour_translate_usage(krb5_keyusage usage)
+{
+ switch (usage) {
+ case 1: /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, */
+ return 1;
+ case 2: /* ticket from kdc */
+ return 2;
+ case 3: /* as-rep encrypted part */
+ return 8;
+ case 4: /* tgs-req authz data */
+ return 4;
+ case 5: /* tgs-req authz data in subkey */
+ return 5;
+ case 6: /* tgs-req authenticator cksum */
+ return 6;
+case 7: /* tgs-req authenticator */
+ return 7;
+ case 8:
+ return 8;
+ case 9: /* tgs-rep encrypted with subkey */
+ return 9;
+ case 10: /* ap-rep authentication cksum */
+ return 10; /* xxx Microsoft never uses this*/
+ case 11: /* app-req authenticator */
+ return 11;
+ case 12: /* app-rep encrypted part */
+ return 12;
+ case 23: /* sign wrap token*/
+ return 13;
+ default:
+ return usage;
+}
+}
+
+/* RFC 4757 */
+krb5_error_code
+krb5_arcfour_encrypt(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key, krb5_keyusage usage,
+ const krb5_data *ivec, const krb5_data *input,
+ krb5_data *output)
+{
+ krb5_keyblock k1, k2, k3;
+ krb5_data d1, d2, d3, salt, plaintext, checksum, ciphertext, confounder;
+ krb5_keyusage ms_usage;
+ size_t keylength, keybytes, blocksize, hashsize;
+ krb5_error_code ret;
+
+ blocksize = enc->block_size;
+ keybytes = enc->keybytes;
+ keylength = enc->keylength;
+ hashsize = hash->hashsize;
+
+ d1.length=keybytes;
+ d1.data=malloc(d1.length);
+ if (d1.data == NULL)
+ return (ENOMEM);
+ k1 = *key;
+ k1.length=d1.length;
+ k1.contents= (void *) d1.data;
+
+ d2.length=keybytes;
+ d2.data=malloc(d2.length);
+ if (d2.data == NULL) {
+ free(d1.data);
+ return (ENOMEM);
+ }
+ k2 = *key;
+ k2.length=d2.length;
+ k2.contents=(void *) d2.data;
+
+ d3.length=keybytes;
+ d3.data=malloc(d3.length);
+ if (d3.data == NULL) {
+ free(d1.data);
+ free(d2.data);
+ return (ENOMEM);
+ }
+ k3 = *key;
+ k3.length=d3.length;
+ k3.contents= (void *) d3.data;
+
+ salt.length=14;
+ salt.data=malloc(salt.length);
+ if (salt.data == NULL) {
+ free(d1.data);
+ free(d2.data);
+ free(d3.data);
+ return (ENOMEM);
+ }
+
+ /* is "input" already blocksize aligned? if it is, then we need this
+ step, otherwise we do not */
+ plaintext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize);
+ plaintext.data=malloc(plaintext.length);
+ if (plaintext.data == NULL) {
+ free(d1.data);
+ free(d2.data);
+ free(d3.data);
+ free(salt.data);
+ return(ENOMEM);
+ }
+
+ /* setup convienient pointers into the allocated data */
+ checksum.length=hashsize;
+ checksum.data=output->data;
+ ciphertext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize);
+ ciphertext.data=output->data+hashsize;
+ confounder.length=CONFOUNDERLENGTH;
+ confounder.data=plaintext.data;
+ output->length = plaintext.length+hashsize;
+
+ /* begin the encryption, computer K1 */
+ ms_usage=krb5int_arcfour_translate_usage(usage);
+ if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
+ strncpy(salt.data, krb5int_arcfour_l40, salt.length);
+ store_32_le(ms_usage, salt.data+10);
+ } else {
+ salt.length=4;
+ store_32_le(ms_usage, salt.data);
+ }
+ krb5_hmac(hash, key, 1, &salt, &d1);
+
+ memcpy(k2.contents, k1.contents, k2.length);
+
+ if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP)
+ memset(k1.contents+7, 0xab, 9);
+
+ ret=krb5_c_random_make_octets(/* XXX */ 0, &confounder);
+ memcpy(plaintext.data+confounder.length, input->data, input->length);
+ if (ret)
+ goto cleanup;
+
+ krb5_hmac(hash, &k2, 1, &plaintext, &checksum);
+
+ krb5_hmac(hash, &k1, 1, &checksum, &d3);
+
+ ret=(*(enc->encrypt))(&k3, ivec, &plaintext, &ciphertext);
+
+ cleanup:
+ memset(d1.data, 0, d1.length);
+ memset(d2.data, 0, d2.length);
+ memset(d3.data, 0, d3.length);
+ memset(salt.data, 0, salt.length);
+ memset(plaintext.data, 0, plaintext.length);
+
+ free(d1.data);
+ free(d2.data);
+ free(d3.data);
+ free(salt.data);
+ free(plaintext.data);
+ return (ret);
+}
+
+/* This is the arcfour-hmac decryption routine */
+krb5_error_code
+krb5_arcfour_decrypt(const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key, krb5_keyusage usage,
+ const krb5_data *ivec, const krb5_data *input,
+ krb5_data *output)
+{
+ krb5_keyblock k1,k2,k3;
+ krb5_data d1,d2,d3,salt,ciphertext,plaintext,checksum;
+ krb5_keyusage ms_usage;
+ size_t keybytes, keylength, hashsize, blocksize;
+ krb5_error_code ret;
+
+ blocksize = enc->block_size;
+ keybytes = enc->keybytes;
+ keylength = enc->keylength;
+ hashsize = hash->hashsize;
+
+ d1.length=keybytes;
+ d1.data=malloc(d1.length);
+ if (d1.data == NULL)
+ return (ENOMEM);
+ k1 = *key;
+ k1.length=d1.length;
+ k1.contents= (void *) d1.data;
+
+ d2.length=keybytes;
+ d2.data=malloc(d2.length);
+ if (d2.data == NULL) {
+ free(d1.data);
+ return (ENOMEM);
+ }
+ k2 = *key;
+ k2.length=d2.length;
+ k2.contents= (void *) d2.data;
+
+ d3.length=keybytes;
+ d3.data=malloc(d3.length);
+ if (d3.data == NULL) {
+ free(d1.data);
+ free(d2.data);
+ return (ENOMEM);
+ }
+ k3 = *key;
+ k3.length=d3.length;
+ k3.contents= (void *) d3.data;
+
+ salt.length=14;
+ salt.data=malloc(salt.length);
+ if(salt.data==NULL) {
+ free(d1.data);
+ free(d2.data);
+ free(d3.data);
+ return (ENOMEM);
+ }
+
+ ciphertext.length=input->length-hashsize;
+ ciphertext.data=input->data+hashsize;
+ plaintext.length=ciphertext.length;
+ plaintext.data=malloc(plaintext.length);
+ if (plaintext.data == NULL) {
+ free(d1.data);
+ free(d2.data);
+ free(d3.data);
+ free(salt.data);
+ return (ENOMEM);
+ }
+
+ checksum.length=hashsize;
+ checksum.data=input->data;
+
+ ms_usage=krb5int_arcfour_translate_usage(usage);
+
+ /* We may have to try two ms_usage values; see below. */
+ do {
+ /* compute the salt */
+ if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
+ strncpy(salt.data, krb5int_arcfour_l40, salt.length);
+ store_32_le(ms_usage, salt.data + 10);
+ } else {
+ salt.length = 4;
+ store_32_le(ms_usage, salt.data);
+ }
+ ret = krb5_hmac(hash, key, 1, &salt, &d1);
+ if (ret)
+ goto cleanup;
+
+ memcpy(k2.contents, k1.contents, k2.length);
+
+ if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
+ memset(k1.contents + 7, 0xab, 9);
+
+ ret = krb5_hmac(hash, &k1, 1, &checksum, &d3);
+ if (ret)
+ goto cleanup;
+
+ ret = (*(enc->decrypt))(&k3, ivec, &ciphertext, &plaintext);
+ if (ret)
+ goto cleanup;
+
+ ret = krb5_hmac(hash, &k2, 1, &plaintext, &d1);
+ if (ret)
+ goto cleanup;
+
+ if (memcmp(checksum.data, d1.data, hashsize) != 0) {
+ if (ms_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.
+ */
+ ms_usage = 8;
+ continue;
+ }
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto cleanup;
+ }
+
+ break;
+ } while (1);
+
+ memcpy(output->data, plaintext.data+CONFOUNDERLENGTH,
+ (plaintext.length-CONFOUNDERLENGTH));
+ output->length=plaintext.length-CONFOUNDERLENGTH;
+
+ cleanup:
+ memset(d1.data, 0, d1.length);
+ memset(d2.data, 0, d2.length);
+ memset(d3.data, 0, d2.length);
+ memset(salt.data, 0, salt.length);
+ memset(plaintext.data, 0, plaintext.length);
+
+ free(d1.data);
+ free(d2.data);
+ free(d3.data);
+ free(salt.data);
+ free(plaintext.data);
+ return (ret);
+}
+
diff --git a/src/lib/crypto/openssl/arcfour/arcfour.h b/src/lib/crypto/openssl/arcfour/arcfour.h
new file mode 100644
index 0000000..be408fe
--- /dev/null
+++ b/src/lib/crypto/openssl/arcfour/arcfour.h
@@ -0,0 +1,43 @@
+#ifndef ARCFOUR_H
+#define ARCFOUR_H
+
+extern void
+krb5_arcfour_encrypt_length(const struct krb5_enc_provider *,
+ const struct krb5_hash_provider *,
+ size_t,
+ size_t *);
+
+extern
+krb5_error_code krb5_arcfour_encrypt(const struct krb5_enc_provider *,
+ const struct krb5_hash_provider *,
+ const krb5_keyblock *,
+ krb5_keyusage,
+ const krb5_data *,
+ const krb5_data *,
+ krb5_data *);
+
+extern
+krb5_error_code krb5_arcfour_decrypt(const struct krb5_enc_provider *,
+ const struct krb5_hash_provider *,
+ const krb5_keyblock *,
+ krb5_keyusage,
+ const krb5_data *,
+ const krb5_data *,
+ krb5_data *);
+
+extern krb5_error_code krb5int_arcfour_string_to_key(
+ const struct krb5_enc_provider *,
+ const krb5_data *,
+ const krb5_data *,
+ const krb5_data *,
+ krb5_keyblock *);
+
+extern const struct krb5_enc_provider krb5int_enc_arcfour;
+extern const struct krb5_aead_provider krb5int_aead_arcfour;
+ krb5_error_code krb5int_arcfour_prf(
+ const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key,
+ const krb5_data *in, krb5_data *out);
+
+#endif /* ARCFOUR_H */
diff --git a/src/lib/crypto/openssl/arcfour/arcfour_aead.c b/src/lib/crypto/openssl/arcfour/arcfour_aead.c
new file mode 100644
index 0000000..cff7d66
--- /dev/null
+++ b/src/lib/crypto/openssl/arcfour/arcfour_aead.c
@@ -0,0 +1,325 @@
+/*
+ * lib/crypto/arcfour/arcfour_aead.c
+ *
+ * Copyright 2008 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+
+#include "k5-int.h"
+#include "arcfour.h"
+#include "arcfour-int.h"
+#include "aead.h"
+
+/* AEAD */
+
+static krb5_error_code
+krb5int_arcfour_crypto_length(const struct krb5_aead_provider *aead,
+ const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ krb5_cryptotype type,
+ unsigned int *length)
+{
+ switch (type) {
+ case KRB5_CRYPTO_TYPE_HEADER:
+ *length = hash->hashsize + CONFOUNDERLENGTH;
+ break;
+ case KRB5_CRYPTO_TYPE_PADDING:
+ *length = 0;
+ break;
+ case KRB5_CRYPTO_TYPE_TRAILER:
+ *length = 0;
+ break;
+ case KRB5_CRYPTO_TYPE_CHECKSUM:
+ *length = hash->hashsize;
+ break;
+ default:
+ assert(0 && "invalid cryptotype passed to krb5int_arcfour_crypto_length");
+ break;
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+alloc_derived_key(const struct krb5_enc_provider *enc,
+ krb5_keyblock *dst,
+ krb5_data *data,
+ const krb5_keyblock *src)
+{
+ data->length = enc->keybytes;
+ data->data = malloc(data->length);
+ if (data->data == NULL)
+ return ENOMEM;
+
+ *dst = *src;
+ dst->length = data->length;
+ dst->contents = (void *)data->data;
+
+ return 0;
+}
+
+static krb5_error_code
+krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead,
+ const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key,
+ krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ krb5_error_code ret;
+ krb5_crypto_iov *header, *trailer;
+ krb5_keyblock k1, k2, k3;
+ krb5_data d1, d2, d3;
+ krb5_data checksum, confounder, header_data;
+ krb5_keyusage ms_usage;
+ char salt_data[14];
+ krb5_data salt;
+ size_t i;
+
+ d1.length = d2.length = d3.length = 0;
+ d1.data = d2.data = d3.data = NULL;
+
+ /*
+ * 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 = alloc_derived_key(enc, &k1, &d1, key);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = alloc_derived_key(enc, &k2, &d2, key);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = alloc_derived_key(enc, &k3, &d3, key);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Begin the encryption, compute K1 */
+ salt.data = salt_data;
+ salt.length = sizeof(salt_data);
+
+ ms_usage = krb5int_arcfour_translate_usage(usage);
+
+ if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
+ strncpy(salt.data, krb5int_arcfour_l40, salt.length);
+ store_32_le(ms_usage, salt.data + 10);
+ } else {
+ salt.length = 4;
+ store_32_le(ms_usage, salt.data);
+ }
+ ret = krb5_hmac(hash, key, 1, &salt, &d1);
+ if (ret != 0)
+ goto cleanup;
+
+ memcpy(k2.contents, k1.contents, k2.length);
+
+ if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
+ memset(k1.contents + 7, 0xAB, 9);
+
+ header->data.length = hash->hashsize + CONFOUNDERLENGTH;
+
+ confounder.data = header->data.data + hash->hashsize;
+ confounder.length = CONFOUNDERLENGTH;
+
+ ret = krb5_c_random_make_octets(0, &confounder);
+ if (ret != 0)
+ goto cleanup;
+
+ checksum.data = header->data.data;
+ checksum.length = hash->hashsize;
+
+ /* Adjust pointers so confounder is at start of header */
+ header->data.length -= hash->hashsize;
+ header->data.data += hash->hashsize;
+
+ ret = krb5int_hmac_iov(hash, &k2, data, num_data, &checksum);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = krb5_hmac(hash, &k1, 1, &checksum, &d3);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = enc->encrypt_iov(&k3, ivec, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+
+cleanup:
+ header->data = header_data; /* restore header pointers */
+
+ if (d1.data != NULL) {
+ memset(d1.data, 0, d1.length);
+ free(d1.data);
+ }
+ if (d2.data != NULL) {
+ memset(d2.data, 0, d2.length);
+ free(d2.data);
+ }
+ if (d3.data != NULL) {
+ memset(d3.data, 0, d3.length);
+ free(d3.data);
+ }
+
+ return ret;
+}
+
+static krb5_error_code
+krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead,
+ const struct krb5_enc_provider *enc,
+ const struct krb5_hash_provider *hash,
+ const krb5_keyblock *key,
+ krb5_keyusage usage,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ krb5_error_code ret;
+ krb5_crypto_iov *header, *trailer;
+ krb5_keyblock k1, k2, k3;
+ krb5_data d1, d2, d3;
+ krb5_data checksum, header_data;
+ krb5_keyusage ms_usage;
+ char salt_data[14];
+ krb5_data salt;
+
+ d1.length = d2.length = d3.length = 0;
+ d1.data = d2.data = d3.data = NULL;
+
+ 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;
+
+ ret = alloc_derived_key(enc, &k1, &d1, key);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = alloc_derived_key(enc, &k2, &d2, key);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = alloc_derived_key(enc, &k3, &d3, key);
+ if (ret != 0)
+ goto cleanup;
+
+ /* Begin the decryption, compute K1 */
+ salt.data = salt_data;
+ salt.length = sizeof(salt_data);
+
+ ms_usage = krb5int_arcfour_translate_usage(usage);
+
+ if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
+ strncpy(salt.data, krb5int_arcfour_l40, salt.length);
+ store_32_le(ms_usage, (unsigned char *)salt.data + 10);
+ } else {
+ salt.length = 4;
+ store_32_le(ms_usage, (unsigned char *)salt.data);
+ }
+ ret = krb5_hmac(hash, key, 1, &salt, &d1);
+ if (ret != 0)
+ goto cleanup;
+
+ memcpy(k2.contents, k1.contents, k2.length);
+
+ if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP)
+ memset(k1.contents + 7, 0xAB, 9);
+
+ checksum.data = header->data.data;
+ checksum.length = hash->hashsize;
+
+ /* Adjust pointers so confounder is at start of header */
+ header->data.length -= hash->hashsize;
+ header->data.data += hash->hashsize;
+
+ ret = krb5_hmac(hash, &k1, 1, &checksum, &d3);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = enc->decrypt_iov(&k3, ivec, data, num_data);
+ if (ret != 0)
+ goto cleanup;
+
+ ret = krb5int_hmac_iov(hash, &k2, data, num_data, &d1);
+ if (ret != 0)
+ goto cleanup;
+
+ if (memcmp(checksum.data, d1.data, hash->hashsize) != 0) {
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ goto cleanup;
+ }
+
+cleanup:
+ header->data = header_data; /* restore header pointers */
+
+ if (d1.data != NULL) {
+ memset(d1.data, 0, d1.length);
+ free(d1.data);
+ }
+ if (d2.data != NULL) {
+ memset(d2.data, 0, d2.length);
+ free(d2.data);
+ }
+ if (d3.data != NULL) {
+ memset(d3.data, 0, d3.length);
+ free(d3.data);
+ }
+
+ return ret;
+}
+
+const struct krb5_aead_provider krb5int_aead_arcfour = {
+ krb5int_arcfour_crypto_length,
+ krb5int_arcfour_encrypt_iov,
+ krb5int_arcfour_decrypt_iov
+};
+
diff --git a/src/lib/crypto/openssl/arcfour/arcfour_s2k.c b/src/lib/crypto/openssl/arcfour/arcfour_s2k.c
new file mode 100644
index 0000000..41053ed
--- /dev/null
+++ b/src/lib/crypto/openssl/arcfour/arcfour_s2k.c
@@ -0,0 +1,59 @@
+#include "k5-int.h"
+#include "k5-utf8.h"
+#include "rsa-md4.h"
+#include "arcfour-int.h"
+
+#if TARGET_OS_MAC && !defined(DEPEND)
+#include <CoreFoundation/CFString.h>
+#endif
+
+krb5_error_code
+krb5int_arcfour_string_to_key(const struct krb5_enc_provider *enc,
+ const krb5_data *string, const krb5_data *salt,
+ const krb5_data *params, krb5_keyblock *key)
+{
+ krb5_error_code err = 0;
+ krb5_MD4_CTX md4_context;
+ 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*/
+
+ /* compute the space needed for the new string.
+ Since the password must be stored in unicode, we need to increase
+ that number by 2x.
+ */
+
+ err = krb5int_utf8cs_to_ucs2les(string->data, string->length, &copystr, &copystrlen);
+ if (err)
+ return err;
+
+ /* the actual MD4 hash of the data */
+ krb5_MD4Init(&md4_context);
+ krb5_MD4Update(&md4_context, copystr, copystrlen);
+ krb5_MD4Final(&md4_context);
+ memcpy(key->contents, md4_context.digest, 16);
+
+#if 0
+ /* test the string_to_key function */
+ printf("Hash=");
+ {
+ int counter;
+ for(counter=0;counter<16;counter++)
+ printf("%02x", md4_context.digest[counter]);
+ printf("\n");
+ }
+#endif /* 0 */
+
+ /* Zero out the data behind us */
+ memset(copystr, 0, copystrlen);
+ memset(&md4_context, 0, sizeof(md4_context));
+ free(copystr);
+ return err;
+}
diff --git a/src/lib/crypto/openssl/des/afsstring2key.c b/src/lib/crypto/openssl/des/afsstring2key.c
new file mode 100644
index 0000000..031db58
--- /dev/null
+++ b/src/lib/crypto/openssl/des/afsstring2key.c
@@ -0,0 +1,27 @@
+/* lib/crypto/openss/des/afsstring2key.c
+ *
+ * Copyright 2009 by the Massachusetts Institute
+ * of Technology.
+ * All Rights Reserved.
+ *
+ */
+
+#include "k5-int.h"
+#include "des_int.h"
+#include <ctype.h>
+
+krb5_error_code
+mit_afs_string_to_key (krb5_keyblock *keyblock, const krb5_data *data,
+ const krb5_data *salt)
+{
+ return KRB5_CRYPTO_INTERNAL;
+}
+char *
+mit_afs_crypt(const char *pw, const char *salt,
+ char *iobuf)
+{
+ /* Unsupported operation */
+ return NULL;
+}
+
+
diff --git a/src/lib/crypto/openssl/des/d3_aead.c b/src/lib/crypto/openssl/des/d3_aead.c
new file mode 100644
index 0000000..cd99886
--- /dev/null
+++ b/src/lib/crypto/openssl/des/d3_aead.c
@@ -0,0 +1,34 @@
+/* lib/crypto/openssl/des/d3_aead.c
+ *
+ * Copyright 2009 by the Massachusetts Institute
+ * of Technology.
+ * All Rights Reserved.
+ *
+ */
+#include "des_int.h"
+#include "aead.h"
+
+void
+krb5int_des3_cbc_encrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule ks1,
+ const mit_des_key_schedule ks2,
+ const mit_des_key_schedule ks3,
+ mit_des_cblock ivec)
+{
+ /* Unsupported operation */
+ abort();
+}
+
+void
+krb5int_des3_cbc_decrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule ks1,
+ const mit_des_key_schedule ks2,
+ const mit_des_key_schedule ks3,
+ mit_des_cblock ivec)
+{
+ /* Unsupported operation */
+ abort();
+}
+
diff --git a/src/lib/crypto/openssl/des/d3_cbc.c b/src/lib/crypto/openssl/des/d3_cbc.c
new file mode 100644
index 0000000..98caab5
--- /dev/null
+++ b/src/lib/crypto/openssl/des/d3_cbc.c
@@ -0,0 +1,51 @@
+/* lib/crypto/openssl/des/d3_cbc.c
+ *
+ * Copyright 2009 by the Massachusetts Institute
+ * of Technology.
+ * All Rights Reserved.
+ *
+ */
+#include "des_int.h"
+
+/*
+ * Triple-DES CBC encryption mode.
+ */
+
+#undef mit_des3_cbc_encrypt
+int
+mit_des3_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out,
+ unsigned long length, const mit_des_key_schedule ks1,
+ const mit_des_key_schedule ks2,
+ const mit_des_key_schedule ks3,
+ const mit_des_cblock ivec, int enc)
+{
+ /* Unsupported operation */
+ return KRB5_CRYPTO_INTERNAL;
+}
+
+void
+krb5int_des3_cbc_encrypt(const mit_des_cblock *input,
+ mit_des_cblock *output,
+ unsigned long length,
+ const mit_des_key_schedule key,
+ const mit_des_key_schedule ks2,
+ const mit_des_key_schedule ks3,
+ const mit_des_cblock ivec)
+{
+ /* Unsupported operation */
+ abort();
+}
+
+void
+krb5int_des3_cbc_decrypt(const mit_des_cblock *in,
+ mit_des_cblock *out,
+ unsigned long length,
+ const mit_des_key_schedule ks1,
+ const mit_des_key_schedule ks2,
+ const mit_des_key_schedule ks3,
+ const mit_des_cblock ivec)
+{
+ /* Unsupported operation */
+ abort();
+}
+
diff --git a/src/lib/crypto/openssl/des/d3_kysched.c b/src/lib/crypto/openssl/des/d3_kysched.c
new file mode 100644
index 0000000..fb42e79
--- /dev/null
+++ b/src/lib/crypto/openssl/des/d3_kysched.c
@@ -0,0 +1,18 @@
+/* lib/crypto/openssl/des/d3_kysched.c
+ *
+ * Copyright 2009 by the Massachusetts Institute
+ * of Technology.
+ * All Rights Reserved.
+ *
+ */
+
+#include "des_int.h"
+
+int
+mit_des3_key_sched(mit_des3_cblock k, mit_des3_key_schedule schedule)
+{
+ /* Unsupported operation */
+ return KRB5_CRYPTO_INTERNAL;
+}
+
+
diff --git a/src/lib/crypto/openssl/des/des_int.h b/src/lib/crypto/openssl/des/des_int.h
new file mode 100644
index 0000000..fd2024a
--- /dev/null
+++ b/src/lib/crypto/openssl/des/des_int.h
@@ -0,0 +1,377 @@
+/*
+ * lib/crypto/des/des_int.h
+ *
+ * Copyright 1987, 1988, 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.
+ *
+ *
+ * Private include file for the Data Encryption Standard library.
+ */
+
+/*
+ * 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.
+ */
+
+/* only do the whole thing once */
+#ifndef DES_INTERNAL_DEFS
+#define DES_INTERNAL_DEFS
+
+#include "k5-int.h"
+/*
+ * Begin "mit-des.h"
+ */
+#ifndef KRB5_MIT_DES__
+#define KRB5_MIT_DES__
+
+#if defined(__MACH__) && defined(__APPLE__)
+#include <TargetConditionals.h>
+#include <AvailabilityMacros.h>
+#if TARGET_RT_MAC_CFM
+#error "Use KfM 4.0 SDK headers for CFM compilation."
+#endif
+#if defined(DEPRECATED_IN_MAC_OS_X_VERSION_10_5) && !defined(KRB5_SUPRESS_DEPRECATED_WARNINGS)
+#define KRB5INT_DES_DEPRECATED DEPRECATED_IN_MAC_OS_X_VERSION_10_5
+#endif
+#endif /* defined(__MACH__) && defined(__APPLE__) */
+
+/* Macro to add deprecated attribute to DES types and functions */
+/* Currently only defined on Mac OS X 10.5 and later. */
+#ifndef KRB5INT_DES_DEPRECATED
+#define KRB5INT_DES_DEPRECATED
+#endif
+
+#include <limits.h>
+
+#if UINT_MAX >= 0xFFFFFFFFUL
+#define DES_INT32 int
+#define DES_UINT32 unsigned int
+#else
+#define DES_INT32 long
+#define DES_UINT32 unsigned long
+#endif
+
+typedef unsigned char des_cblock[8] /* crypto-block size */
+KRB5INT_DES_DEPRECATED;
+
+/*
+ * Key schedule.
+ *
+ * This used to be
+ *
+ * typedef struct des_ks_struct {
+ * union { DES_INT32 pad; des_cblock _;} __;
+ * } des_key_schedule[16];
+ *
+ * but it would cause trouble if DES_INT32 were ever more than 4
+ * bytes. The reason is that all the encryption functions cast it to
+ * (DES_INT32 *), and treat it as if it were DES_INT32[32]. If
+ * 2*sizeof(DES_INT32) is ever more than sizeof(des_cblock), the
+ * caller-allocated des_key_schedule will be overflowed by the key
+ * scheduling functions. We can't assume that every platform will
+ * have an exact 32-bit int, and nothing should be looking inside a
+ * des_key_schedule anyway.
+ */
+typedef struct des_ks_struct { DES_INT32 _[2]; } des_key_schedule[16]
+KRB5INT_DES_DEPRECATED;
+
+typedef des_cblock mit_des_cblock;
+typedef des_key_schedule mit_des_key_schedule;
+
+/* Triple-DES structures */
+typedef mit_des_cblock mit_des3_cblock[3];
+typedef mit_des_key_schedule mit_des3_key_schedule[3];
+
+#define MIT_DES_ENCRYPT 1
+#define MIT_DES_DECRYPT 0
+
+typedef struct mit_des_ran_key_seed {
+ krb5_encrypt_block eblock;
+ krb5_data sequence;
+} mit_des_random_state;
+
+/* the first byte of the key is already in the keyblock */
+
+#define MIT_DES_BLOCK_LENGTH (8*sizeof(krb5_octet))
+#define MIT_DES_CBC_CRC_PAD_MINIMUM CRC32_CKSUM_LENGTH
+/* This used to be 8*sizeof(krb5_octet) */
+#define MIT_DES_KEYSIZE 8
+
+#define MIT_DES_CBC_CKSUM_LENGTH (4*sizeof(krb5_octet))
+
+/*
+ * Check if k5-int.h has been included before us. If so, then check to see
+ * that our view of the DES key size is the same as k5-int.h's.
+ */
+#ifdef KRB5_MIT_DES_KEYSIZE
+#if MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE
+error(MIT_DES_KEYSIZE does not equal KRB5_MIT_DES_KEYSIZE)
+#endif /* MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE */
+#endif /* KRB5_MIT_DES_KEYSIZE */
+#endif /* KRB5_MIT_DES__ */
+/*
+ * End "mit-des.h"
+ */
+
+/* afsstring2key.c */
+extern krb5_error_code mit_afs_string_to_key
+ (krb5_keyblock *keyblock,
+ const krb5_data *data,
+ const krb5_data *salt);
+extern char *mit_afs_crypt
+ (const char *pw, const char *salt, char *iobuf);
+
+/* f_cksum.c */
+extern unsigned long mit_des_cbc_cksum
+ (const krb5_octet *, krb5_octet *, unsigned long ,
+ const mit_des_key_schedule, const krb5_octet *);
+
+/* f_ecb.c */
+extern int mit_des_ecb_encrypt
+ (const mit_des_cblock *, mit_des_cblock *, mit_des_key_schedule , int );
+
+/* f_cbc.c */
+extern int mit_des_cbc_encrypt (const mit_des_cblock *in,
+ mit_des_cblock *out,
+ unsigned long length,
+ const mit_des_key_schedule schedule,
+ const mit_des_cblock ivec, int enc);
+
+#define mit_des_zeroblock krb5int_c_mit_des_zeroblock
+extern const mit_des_cblock mit_des_zeroblock;
+
+/* fin_rndkey.c */
+extern krb5_error_code mit_des_finish_random_key
+ ( const krb5_encrypt_block *,
+ krb5_pointer *);
+
+/* finish_key.c */
+extern krb5_error_code mit_des_finish_key
+ ( krb5_encrypt_block *);
+
+/* init_rkey.c */
+extern krb5_error_code mit_des_init_random_key
+ ( const krb5_encrypt_block *,
+ const krb5_keyblock *,
+ krb5_pointer *);
+
+/* key_parity.c */
+extern void mit_des_fixup_key_parity (mit_des_cblock );
+extern int mit_des_check_key_parity (mit_des_cblock );
+
+/* key_sched.c */
+extern int mit_des_key_sched
+ (mit_des_cblock , mit_des_key_schedule );
+
+/* process_ky.c */
+extern krb5_error_code mit_des_process_key
+ ( krb5_encrypt_block *, const krb5_keyblock *);
+
+/* random_key.c */
+extern krb5_error_code mit_des_random_key
+ ( const krb5_encrypt_block *, krb5_pointer ,
+ krb5_keyblock **);
+
+/* string2key.c */
+extern krb5_error_code mit_des_string_to_key
+ ( const krb5_encrypt_block *,
+ krb5_keyblock *, const krb5_data *, const krb5_data *);
+extern krb5_error_code mit_des_string_to_key_int
+ (krb5_keyblock *, const krb5_data *, const krb5_data *);
+
+/* weak_key.c */
+extern int mit_des_is_weak_key (mit_des_cblock );
+
+/* cmb_keys.c */
+krb5_error_code mit_des_combine_subkeys
+ (const krb5_keyblock *, const krb5_keyblock *,
+ krb5_keyblock **);
+
+/* f_pcbc.c */
+int mit_des_pcbc_encrypt ();
+
+/* f_sched.c */
+int mit_des_make_key_sched(mit_des_cblock, mit_des_key_schedule);
+
+
+/* misc.c */
+extern void swap_bits (char *);
+extern unsigned long long_swap_bits (unsigned long );
+extern unsigned long swap_six_bits_to_ansi (unsigned long );
+extern unsigned long swap_four_bits_to_ansi (unsigned long );
+extern unsigned long swap_bit_pos_1 (unsigned long );
+extern unsigned long swap_bit_pos_0 (unsigned long );
+extern unsigned long swap_bit_pos_0_to_ansi (unsigned long );
+extern unsigned long rev_swap_bit_pos_0 (unsigned long );
+extern unsigned long swap_byte_bits (unsigned long );
+extern unsigned long swap_long_bytes_bit_number (unsigned long );
+#ifdef FILE
+/* XXX depends on FILE being a #define! */
+extern void test_set (FILE *, const char *, int, const char *, int);
+#endif
+
+/* d3_ecb.c */
+extern int mit_des3_ecb_encrypt
+ (const mit_des_cblock *in,
+ mit_des_cblock *out,
+ mit_des_key_schedule sched1,
+ mit_des_key_schedule sched2,
+ mit_des_key_schedule sched3,
+ int enc);
+
+/* d3_cbc.c */
+extern int mit_des3_cbc_encrypt
+ (const mit_des_cblock *in,
+ mit_des_cblock *out,
+ unsigned long length,
+ const mit_des_key_schedule ks1,
+ const mit_des_key_schedule ks2,
+ const mit_des_key_schedule ks3,
+ const mit_des_cblock ivec,
+ int enc);
+
+void
+krb5int_des3_cbc_encrypt(const mit_des_cblock *in,
+ mit_des_cblock *out,
+ unsigned long length,
+ const mit_des_key_schedule ks1,
+ const mit_des_key_schedule ks2,
+ const mit_des_key_schedule ks3,
+ const mit_des_cblock ivec);
+void
+krb5int_des3_cbc_decrypt(const mit_des_cblock *in,
+ mit_des_cblock *out,
+ unsigned long length,
+ const mit_des_key_schedule ks1,
+ const mit_des_key_schedule ks2,
+ const mit_des_key_schedule ks3,
+ const mit_des_cblock ivec);
+
+void
+krb5int_des3_cbc_encrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule ks1,
+ const mit_des_key_schedule ks2,
+ const mit_des_key_schedule ks3,
+ mit_des_cblock ivec);
+
+void
+krb5int_des3_cbc_decrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule ks1,
+ const mit_des_key_schedule ks2,
+ const mit_des_key_schedule ks3,
+ mit_des_cblock ivec);
+
+#define mit_des3_cbc_encrypt(in,out,length,ks1,ks2,ks3,ivec,enc) \
+ ((enc ? krb5int_des3_cbc_encrypt : krb5int_des3_cbc_decrypt) \
+ (in, out, length, ks1, ks2, ks3, ivec), 0)
+
+void
+krb5int_des_cbc_encrypt(const mit_des_cblock *in,
+ mit_des_cblock *out,
+ unsigned long length,
+ const mit_des_key_schedule schedule,
+ const mit_des_cblock ivec);
+void
+krb5int_des_cbc_decrypt(const mit_des_cblock *in,
+ mit_des_cblock *out,
+ unsigned long length,
+ const mit_des_key_schedule schedule,
+ const mit_des_cblock ivec);
+
+#define mit_des_cbc_encrypt(in,out,length,schedule,ivec,enc) \
+ ((enc ? krb5int_des_cbc_encrypt : krb5int_des_cbc_decrypt) \
+ (in, out, length, schedule, ivec), 0)
+
+void
+krb5int_des_cbc_encrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule schedule,
+ mit_des_cblock ivec);
+
+void
+krb5int_des_cbc_decrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule schedule,
+ mit_des_cblock ivec);
+
+/* d3_procky.c */
+extern krb5_error_code mit_des3_process_key
+ (krb5_encrypt_block * eblock,
+ const krb5_keyblock * keyblock);
+
+/* d3_kysched.c */
+extern int mit_des3_key_sched
+ (mit_des3_cblock key,
+ mit_des3_key_schedule schedule);
+
+/* d3_str2ky.c */
+extern krb5_error_code mit_des3_string_to_key
+ (const krb5_encrypt_block * eblock,
+ krb5_keyblock * keyblock,
+ const krb5_data * data,
+ const krb5_data * salt);
+
+/* u_nfold.c */
+extern krb5_error_code mit_des_n_fold
+ (const krb5_octet * input,
+ const size_t in_len,
+ krb5_octet * output,
+ const size_t out_len);
+
+/* u_rn_key.c */
+extern int mit_des_is_weak_keyblock
+ (krb5_keyblock *keyblock);
+
+extern void mit_des_fixup_keyblock_parity
+ (krb5_keyblock *keyblock);
+
+extern krb5_error_code mit_des_set_random_generator_seed
+ (const krb5_data * seed,
+ krb5_pointer random_state);
+
+extern krb5_error_code mit_des_set_random_sequence_number
+ (const krb5_data * sequence,
+ krb5_pointer random_state);
+#endif /*DES_INTERNAL_DEFS*/
diff --git a/src/lib/crypto/openssl/des/f_aead.c b/src/lib/crypto/openssl/des/f_aead.c
new file mode 100644
index 0000000..2046475
--- /dev/null
+++ b/src/lib/crypto/openssl/des/f_aead.c
@@ -0,0 +1,33 @@
+/* lib/crypto/openssl/des/f_aead.c
+ *
+ * Copyright 2009 by the Massachusetts Institute
+ * of Technology.
+ * All Rights Reserved.
+ *
+ */
+
+#include "des_int.h"
+#include "aead.h"
+
+
+void
+krb5int_des_cbc_encrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule schedule,
+ mit_des_cblock ivec)
+{
+ /* Unsupported operation */
+ abort();
+}
+
+void
+krb5int_des_cbc_decrypt_iov(krb5_crypto_iov *data,
+ unsigned long num_data,
+ const mit_des_key_schedule schedule,
+ mit_des_cblock iv)
+{
+ /* Unsupported operation */
+ abort();
+}
+
+
diff --git a/src/lib/crypto/openssl/des/f_cbc.c b/src/lib/crypto/openssl/des/f_cbc.c
new file mode 100644
index 0000000..55b648f
--- /dev/null
+++ b/src/lib/crypto/openssl/des/f_cbc.c
@@ -0,0 +1,89 @@
+/*
+ * lib/crypto/openssldes/f_cbc.c
+ *
+ * Copyright (C) 1990 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.
+ *
+ * DES implementation donated by Dennis Ferguson
+ */
+
+/*
+ * des_cbc_encrypt.c - an implementation of the DES cipher function in cbc mode
+ */
+#include "des_int.h"
+
+/*
+ * des_cbc_encrypt - {en,de}crypt a stream in CBC mode
+ */
+
+/*
+ * This routine performs DES cipher-block-chaining operation, either
+ * encrypting from cleartext to ciphertext, if encrypt != 0 or
+ * decrypting from ciphertext to cleartext, if encrypt == 0.
+ *
+ * The key schedule is passed as an arg, as well as the cleartext or
+ * ciphertext. The cleartext and ciphertext should be in host order.
+ *
+ * NOTE-- the output is ALWAYS an multiple of 8 bytes long. If not
+ * enough space was provided, your program will get trashed.
+ *
+ * For encryption, the cleartext string is null padded, at the end, to
+ * an integral multiple of eight bytes.
+ *
+ * For decryption, the ciphertext will be used in integral multiples
+ * of 8 bytes, but only the first "length" bytes returned into the
+ * cleartext.
+ */
+
+const mit_des_cblock mit_des_zeroblock /* = all zero */;
+
+#undef mit_des_cbc_encrypt
+int
+mit_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out,
+ unsigned long length, const mit_des_key_schedule schedule,
+ const mit_des_cblock ivec, int enc)
+{
+ /* Unsupported operation */
+ return KRB5_CRYPTO_INTERNAL;
+}
+void
+krb5int_des_cbc_encrypt(const mit_des_cblock *in,
+ mit_des_cblock *out,
+ unsigned long length,
+ const mit_des_key_schedule schedule,
+ const mit_des_cblock ivec)
+{
+ /* Unsupported operation */
+ abort();
+}
+
+void
+krb5int_des_cbc_decrypt(const mit_des_cblock *in,
+ mit_des_cblock *out,
+ unsigned long length,
+ const mit_des_key_schedule schedule,
+ const mit_des_cblock ivec)
+{
+ /* Unsupported operation */
+ abort();
+}
+
diff --git a/src/lib/crypto/openssl/des/f_cksum.c b/src/lib/crypto/openssl/des/f_cksum.c
new file mode 100644
index 0000000..c49c8fd
--- /dev/null
+++ b/src/lib/crypto/openssl/des/f_cksum.c
@@ -0,0 +1,18 @@
+/*
+ * lib/crypto/openssl/des/f_cksum.c
+ *
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ */
+
+#include "des_int.h"
+
+unsigned long
+mit_des_cbc_cksum(const krb5_octet *in, krb5_octet *out,
+ unsigned long length, const mit_des_key_schedule schedule,
+ const krb5_octet *ivec)
+{
+ /* Unsupported operation */
+ return KRB5_CRYPTO_INTERNAL;
+}
+
diff --git a/src/lib/crypto/openssl/des/f_parity.c b/src/lib/crypto/openssl/des/f_parity.c
new file mode 100644
index 0000000..1a83db6
--- /dev/null
+++ b/src/lib/crypto/openssl/des/f_parity.c
@@ -0,0 +1,29 @@
+/*
+ * lib/crypto/openssl/des/f_parity.c
+ *
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ */
+
+#include "des_int.h"
+#include <openssl/des.h>
+
+void
+mit_des_fixup_key_parity(mit_des_cblock key)
+{
+ DES_set_odd_parity(key);
+}
+
+/*
+ * des_check_key_parity: returns true iff key has the correct des parity.
+ * See des_fix_key_parity for the definition of
+ * correct des parity.
+ */
+int
+mit_des_check_key_parity(mit_des_cblock key)
+{
+ if (!DES_check_key_parity(key))
+ return(0);
+ return (1);
+}
+
diff --git a/src/lib/crypto/openssl/des/f_sched.c b/src/lib/crypto/openssl/des/f_sched.c
new file mode 100644
index 0000000..e833132
--- /dev/null
+++ b/src/lib/crypto/openssl/des/f_sched.c
@@ -0,0 +1,15 @@
+/*
+ * lib/crypto/openssl/des/f_sched.c
+ *
+ * Copyright (C) 2009 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ */
+
+#include "des_int.h"
+
+int
+mit_des_make_key_sched(mit_des_cblock key, mit_des_key_schedule schedule)
+{
+ return KRB5_CRYPTO_INTERNAL; // CRYPTO_UNSOPPERTED_OP
+}
+
diff --git a/src/lib/crypto/openssl/des/f_tables.c b/src/lib/crypto/openssl/des/f_tables.c
new file mode 100644
index 0000000..a8d161d
--- /dev/null
+++ b/src/lib/crypto/openssl/des/f_tables.c
@@ -0,0 +1,17 @@
+/*
+ * lib/crypto/openssl/des/f_tables.c
+ *
+ * Copyright 2009 by the Massachusetts Institute
+ * of Technology.
+ * All Rights Reserved.
+ *
+ */
+
+#include "des_int.h"
+#include "f_tables.h"
+
+const unsigned DES_INT32 des_IP_table[] = {};
+const unsigned DES_INT32 des_FP_table[] = {};
+const unsigned DES_INT32 des_SP_table[] = {};
+
+
diff --git a/src/lib/crypto/openssl/des/f_tables.h b/src/lib/crypto/openssl/des/f_tables.h
new file mode 100644
index 0000000..af20cd5
--- /dev/null
+++ b/src/lib/crypto/openssl/des/f_tables.h
@@ -0,0 +1,9 @@
+/*
+ * lib/crypto/des/f_tables.h
+ *
+ * Copyright 2009 by the Massachusetts Institute
+ * of Technology.
+ * All Rights Reserved.
+ *
+ */
+
diff --git a/src/lib/crypto/openssl/des/key_sched.c b/src/lib/crypto/openssl/des/key_sched.c
new file mode 100644
index 0000000..1007ec9
--- /dev/null
+++ b/src/lib/crypto/openssl/des/key_sched.c
@@ -0,0 +1,18 @@
+/*
+ * lib/crypto/openssl/des/key_sched.c
+ *
+ * Copyright 2009 by the Massachusetts Institute
+ * of Technology.
+ * All Rights Reserved.
+ *
+ */
+
+#include "des_int.h"
+
+int
+mit_des_key_sched(mit_des_cblock k, mit_des_key_schedule schedule)
+{
+ /* Unsupported operation */
+ return KRB5_CRYPTO_INTERNAL;
+}
+
diff --git a/src/lib/crypto/openssl/des/string2key.c b/src/lib/crypto/openssl/des/string2key.c
new file mode 100644
index 0000000..775a153
--- /dev/null
+++ b/src/lib/crypto/openssl/des/string2key.c
@@ -0,0 +1,26 @@
+/*
+ * lib/crypto/openssl/des/string2key.c
+ *
+ * Copyright 2009 by the Massachusetts Institute
+ * of Technology.
+ * All Rights Reserved.
+ *
+ */
+
+#include "des_int.h"
+#include <openssl/des.h>
+
+
+krb5_error_code
+mit_des_string_to_key_int (krb5_keyblock *key,
+ const krb5_data *pw, const krb5_data *salt)
+{
+ DES_cblock outkey;
+ DES_string_to_key(pw->data, &outkey);
+ if ( key->length < sizeof(outkey))
+ return KRB5_CRYPTO_INTERNAL;
+ key->length = sizeof(outkey);
+ memcpy(key->contents, outkey, key->length);
+ return 0;
+}
+
diff --git a/src/lib/crypto/openssl/des/weak_key.c b/src/lib/crypto/openssl/des/weak_key.c
new file mode 100644
index 0000000..7f97083
--- /dev/null
+++ b/src/lib/crypto/openssl/des/weak_key.c
@@ -0,0 +1,87 @@
+/*
+ * lib/crypto/openssl/des/weak_key.c
+ *
+ * Copyright 1989,1990,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.
+ *
+ *
+ * Under U.S. law, this software may not be exported outside the US
+ * without license from the U.S. Commerce department.
+ *
+ * These routines form the library interface to the DES facilities.
+ *
+ * Originally written 8/85 by Steve Miller, MIT Project Athena.
+ */
+
+#include "des_int.h"
+
+/*
+ * The following are the weak DES keys:
+ */
+static const mit_des_cblock weak[16] = {
+ /* weak keys */
+ {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
+ {0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe},
+ {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e},
+ {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1},
+
+ /* semi-weak */
+ {0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe},
+ {0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01},
+
+ {0x1f,0xe0,0x1f,0xe0,0x0e,0xf1,0x0e,0xf1},
+ {0xe0,0x1f,0xe0,0x1f,0xf1,0x0e,0xf1,0x0e},
+
+ {0x01,0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1},
+ {0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1,0x01},
+
+ {0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e,0xfe},
+ {0xfe,0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e},
+
+ {0x01,0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e},
+ {0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e,0x01},
+
+ {0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1,0xfe},
+ {0xfe,0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1}
+};
+
+/*
+ * mit_des_is_weak_key: returns true iff key is a [semi-]weak des key.
+ *
+ * Requires: key has correct odd parity.
+ */
+int
+mit_des_is_weak_key(mit_des_cblock key)
+{
+ unsigned int i;
+ const mit_des_cblock *weak_p = weak;
+
+ for (i = 0; i < (sizeof(weak)/sizeof(mit_des_cblock)); i++) {
+ if (!memcmp(weak_p++,key,sizeof(mit_des_cblock)))
+ return 1;
+ }
+ if ( DES_is_weak_key(key) == 1) /* Also OpenSSL's check */
+ return 1;
+
+ return 0;
+}
+
diff --git a/src/lib/crypto/openssl/enc_provider/aes.c b/src/lib/crypto/openssl/enc_provider/aes.c
new file mode 100644
index 0000000..c167818
--- /dev/null
+++ b/src/lib/crypto/openssl/enc_provider/aes.c
@@ -0,0 +1,505 @@
+/*
+ * lib/crypto/openssl/enc_provider/aes.c
+ *
+ * Copyright (C) 2003, 2007, 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 "k5-int.h"
+#include "enc_provider.h"
+#include "aes.h"
+#include <aead.h>
+#include <hash_provider/hash_provider.h>
+#include <openssl/evp.h>
+#include <openssl/aes.h>
+#include <openssl/modes.h>
+#include <rand2key.h>
+
+/* proto's */
+static krb5_error_code
+cts_enc(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output);
+static krb5_error_code
+cbc_enc(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output);
+static krb5_error_code
+cts_decr(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output);
+static krb5_error_code
+cbc_decr(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output);
+
+static const EVP_CIPHER *
+map_mode( unsigned int len)
+{
+ if (len==16)
+ return EVP_aes_128_cbc();
+ if (len==32)
+ return EVP_aes_256_cbc();
+ else
+ return NULL;
+}
+
+static inline void enc(char *out, const char *in, aes_ctx *ctx)
+{
+ if (aes_enc_blk((const unsigned char *)in, (unsigned char *)out, ctx)
+ != aes_good)
+ abort();
+}
+static inline void dec(char *out, const char *in, aes_ctx *ctx)
+{
+ if (aes_dec_blk((const unsigned char *)in, (unsigned char *)out, ctx)
+ != aes_good)
+ abort();
+}
+static void xorblock(char *out, const char *in)
+{
+ int z;
+ for (z = 0; z < BLOCK_SIZE; z++)
+ out[z] ^= in[z];
+}
+
+
+static krb5_error_code
+cbc_enc(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ EVP_CIPHER_CTX ciph_ctx;
+ unsigned char *key_buf = NULL;
+ unsigned char *tmp_buf = NULL;
+ int ret = 0, tmp_len = 0;
+
+ key_buf = OPENSSL_malloc(key->length);
+ if (!key_buf)
+ return ENOMEM;
+ tmp_len = input->length;
+ tmp_buf = OPENSSL_malloc(input->length);
+ if (!tmp_buf){
+ OPENSSL_free(key_buf);
+ return ENOMEM;
+ }
+ memcpy(key_buf, key->contents, key->length);
+
+ EVP_CIPHER_CTX_init(&ciph_ctx);
+
+ if (ivec && ivec->data && (ivec->length <= EVP_MAX_IV_LENGTH)){
+ ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->length),
+ NULL, key_buf, (unsigned char*)ivec->data);
+ } else {
+ ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->length),
+ NULL, key_buf, NULL);
+ }
+
+ if (ret == 1){
+ EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+ ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len,
+ (unsigned char *)input->data, input->length);
+
+ output->length = tmp_len;
+ if(ret)
+ ret = EVP_EncryptFinal_ex(&ciph_ctx,tmp_buf+tmp_len,&tmp_len);
+ }
+
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+ if (ret == 1){
+ memcpy(output->data, tmp_buf, output->length);
+ ret = 0;
+ } else {
+ ret = KRB5_CRYPTO_INTERNAL;
+ }
+
+ OPENSSL_free(key_buf);
+ OPENSSL_free(tmp_buf);
+
+ return ret;
+}
+
+static krb5_error_code
+cbc_decr(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ int ret = 0;
+ int tmp_len = 0;
+ unsigned char *key_buf = NULL;
+ unsigned char *tmp_buf = NULL;
+ EVP_CIPHER_CTX ciph_ctx;
+
+
+ key_buf = OPENSSL_malloc(key->length);
+ if (!key_buf)
+ return ENOMEM;
+ tmp_len = input->length;
+ tmp_buf = OPENSSL_malloc(input->length);
+ if (!tmp_buf){
+ OPENSSL_free(key_buf);
+ return ENOMEM;
+ }
+ memcpy(key_buf, key->contents, key->length);
+
+ EVP_CIPHER_CTX_init(&ciph_ctx);
+
+ if (ivec && ivec->data && (ivec->length <= EVP_MAX_IV_LENGTH)) {
+ ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->length),
+ NULL, key_buf, (unsigned char*)ivec->data);
+ } else
+ ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->length),
+ NULL, key_buf, NULL);
+
+ if (ret == 1) {
+ EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+ ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len,
+ (unsigned char *)input->data, input->length);
+ output->length = tmp_len;
+ if (ret == 1)
+ ret = EVP_DecryptFinal_ex(&ciph_ctx,tmp_buf+tmp_len,&tmp_len);
+ }
+
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+ if (ret == 1) {
+ output->length += tmp_len;
+ memcpy(output->data, tmp_buf, output->length);
+ ret = 0;
+ } else {
+ ret = KRB5_CRYPTO_INTERNAL;
+ }
+
+ OPENSSL_free(key_buf);
+ OPENSSL_free(tmp_buf);
+
+ return ret;
+}
+
+static krb5_error_code
+cts_enc(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ size_t size = 0;
+ int ret = 0, tmp_len = 0;
+ unsigned char iv_cts[EVP_MAX_IV_LENGTH*4];
+ unsigned char *tmp_buf = NULL;
+ AES_KEY enck;
+
+ memset(iv_cts,0,sizeof(iv_cts));
+ if (ivec && ivec->data && (ivec->length <= sizeof(iv_cts)))
+ memcpy(iv_cts, ivec->data,ivec->length);
+
+ tmp_buf = OPENSSL_malloc(input->length);
+ if (!tmp_buf)
+ return ENOMEM;
+ tmp_len = input->length;
+
+ AES_set_encrypt_key(key->contents, 8*key->length, &enck);
+
+ size = CRYPTO_cts128_encrypt((unsigned char *)input->data, tmp_buf,
+ input->length, &enck,
+ iv_cts, (cbc128_f)AES_cbc_encrypt);
+
+ if (size <= 0 || output->length < size) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ } else {
+ output->length = size;
+ memcpy(output->data, tmp_buf, output->length);
+ ret = 0;
+ }
+
+ OPENSSL_free(tmp_buf);
+
+ return ret;
+}
+
+static krb5_error_code
+cts_decr(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ size_t size = 0;
+ int ret = 0, tmp_len = 0;
+ unsigned char iv_cts[EVP_MAX_IV_LENGTH*4];
+ unsigned char *tmp_buf = NULL;
+ AES_KEY deck;
+
+ memset(iv_cts,0,EVP_MAX_IV_LENGTH*4);
+ if (ivec && ivec->data && (ivec->length <= EVP_MAX_IV_LENGTH))
+ memcpy(iv_cts, ivec->data,ivec->length);
+
+ tmp_buf = OPENSSL_malloc(input->length);
+ if (!tmp_buf)
+ return ENOMEM;
+ tmp_len = input->length;
+
+ AES_set_decrypt_key(key->contents, 8*key->length, &deck);
+
+ size = CRYPTO_cts128_decrypt((unsigned char *)input->data, tmp_buf,
+ input->length, &deck,
+ iv_cts, (cbc128_f)AES_cbc_encrypt);
+
+
+ if (size <= 0 || output->length < size) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ } else {
+ output->length = size + 16;
+ memcpy(output->data, tmp_buf, output->length);
+ ret = 0;
+ }
+
+ OPENSSL_free(tmp_buf);
+
+ return ret;
+}
+
+krb5_error_code
+krb5int_aes_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ int ret = 0;
+
+ if ( input->length < BLOCK_SIZE * 2) {
+
+ ret = cbc_enc(key, ivec, input, output);
+
+ } else {
+
+ ret = cts_enc(key, ivec, input, output);
+ }
+
+ return ret;
+}
+
+krb5_error_code
+krb5int_aes_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
+{
+ int ret = 0;
+
+ if ( input->length < BLOCK_SIZE*2) {
+
+ ret = cbc_decr(key, ivec, input, output);
+
+ } else {
+
+ ret = cts_decr(key, ivec, input, output);
+
+ }
+
+ return ret;
+}
+
+static krb5_error_code
+krb5int_aes_encrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ aes_ctx ctx;
+ char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE];
+ int nblocks = 0, blockno;
+ size_t input_length, i;
+
+ if (aes_enc_key(key->contents, key->length, &ctx) != aes_good)
+ abort();
+
+ if (ivec != NULL)
+ memcpy(tmp, ivec->data, BLOCK_SIZE);
+ else
+ memset(tmp, 0, BLOCK_SIZE);
+
+ for (i = 0, input_length = 0; i < num_data; i++) {
+ krb5_crypto_iov *iov = &data[i];
+
+ if (ENCRYPT_IOV(iov))
+ input_length += iov->data.length;
+ }
+
+ nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+ assert(nblocks > 1);
+
+ {
+ char blockN2[BLOCK_SIZE]; /* second last */
+ char blockN1[BLOCK_SIZE]; /* last block */
+ struct iov_block_state input_pos, output_pos;
+
+ IOV_BLOCK_STATE_INIT(&input_pos);
+ IOV_BLOCK_STATE_INIT(&output_pos);
+
+ for (blockno = 0; blockno < nblocks - 2; blockno++) {
+ char blockN[BLOCK_SIZE];
+
+ krb5int_c_iov_get_block((unsigned char *)blockN, BLOCK_SIZE, data, num_data, &input_pos);
+ xorblock(tmp, blockN);
+ enc(tmp2, tmp, &ctx);
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)tmp2, BLOCK_SIZE, &output_pos);
+
+ /* Set up for next block. */
+ memcpy(tmp, tmp2, BLOCK_SIZE);
+ }
+
+ /* Do final CTS step for last two blocks (the second of which
+ may or may not be incomplete). */
+
+ /* First, get the last two blocks */
+ memset(blockN1, 0, sizeof(blockN1)); /* pad last block with zeros */
+ krb5int_c_iov_get_block((unsigned char *)blockN2, BLOCK_SIZE, data, num_data, &input_pos);
+ krb5int_c_iov_get_block((unsigned char *)blockN1, BLOCK_SIZE, data, num_data, &input_pos);
+
+ /* Encrypt second last block */
+ xorblock(tmp, blockN2);
+ enc(tmp2, tmp, &ctx);
+ memcpy(blockN2, tmp2, BLOCK_SIZE); /* blockN2 now contains first block */
+ memcpy(tmp, tmp2, BLOCK_SIZE);
+
+ /* Encrypt last block */
+ xorblock(tmp, blockN1);
+ enc(tmp2, tmp, &ctx);
+ memcpy(blockN1, tmp2, BLOCK_SIZE);
+
+ /* Put the last two blocks back into the iovec (reverse order) */
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN1, BLOCK_SIZE, &output_pos);
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN2, BLOCK_SIZE, &output_pos);
+
+ if (ivec != NULL)
+ memcpy(ivec->data, blockN1, BLOCK_SIZE);
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+krb5int_aes_decrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ aes_ctx ctx;
+ char tmp[BLOCK_SIZE], tmp2[BLOCK_SIZE], tmp3[BLOCK_SIZE];
+ int nblocks = 0, blockno;
+ unsigned int i;
+ size_t input_length;
+
+ if (aes_dec_key(key->contents, key->length, &ctx) != aes_good)
+ abort();
+
+ if (ivec != NULL)
+ memcpy(tmp, ivec->data, BLOCK_SIZE);
+ else
+ memset(tmp, 0, BLOCK_SIZE);
+
+ for (i = 0, input_length = 0; i < num_data; i++) {
+ krb5_crypto_iov *iov = &data[i];
+
+ if (ENCRYPT_IOV(iov))
+ input_length += iov->data.length;
+ }
+
+ nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+ assert(nblocks > 1);
+
+ {
+ char blockN2[BLOCK_SIZE]; /* second last */
+ char blockN1[BLOCK_SIZE]; /* last block */
+ struct iov_block_state input_pos, output_pos;
+
+ IOV_BLOCK_STATE_INIT(&input_pos);
+ IOV_BLOCK_STATE_INIT(&output_pos);
+
+ for (blockno = 0; blockno < nblocks - 2; blockno++) {
+ char blockN[BLOCK_SIZE];
+
+ krb5int_c_iov_get_block((unsigned char *)blockN, BLOCK_SIZE, data, num_data, &input_pos);
+ dec(tmp2, blockN, &ctx);
+ xorblock(tmp2, tmp);
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)tmp2, BLOCK_SIZE, &output_pos);
+ memcpy(tmp, blockN, BLOCK_SIZE);
+ }
+
+ /* Do last two blocks, the second of which (next-to-last block
+ of plaintext) may be incomplete. */
+
+ /* First, get the last two encrypted blocks */
+ memset(blockN1, 0, sizeof(blockN1)); /* pad last block with zeros */
+ krb5int_c_iov_get_block((unsigned char *)blockN2, BLOCK_SIZE, data, num_data, &input_pos);
+ krb5int_c_iov_get_block((unsigned char *)blockN1, BLOCK_SIZE, data, num_data, &input_pos);
+
+ /* Decrypt second last block */
+ dec(tmp2, blockN2, &ctx);
+ /* Set tmp2 to last (possibly partial) plaintext block, and
+ save it. */
+ xorblock(tmp2, blockN1);
+ memcpy(blockN2, tmp2, BLOCK_SIZE);
+
+ /* Maybe keep the trailing part, and copy in the last
+ ciphertext block. */
+ input_length %= BLOCK_SIZE;
+ memcpy(tmp2, blockN1, input_length ? input_length : BLOCK_SIZE);
+ dec(tmp3, tmp2, &ctx);
+ xorblock(tmp3, tmp);
+ /* Copy out ivec first before we clobber blockN1 with plaintext */
+ if (ivec != NULL)
+ memcpy(ivec->data, blockN1, BLOCK_SIZE);
+ memcpy(blockN1, tmp3, BLOCK_SIZE);
+
+ /* Put the last two blocks back into the iovec */
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN1, BLOCK_SIZE, &output_pos);
+ krb5int_c_iov_put_block(data, num_data, (unsigned char *)blockN2, BLOCK_SIZE, &output_pos);
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+krb5int_aes_init_state (const krb5_keyblock *key, krb5_keyusage usage,
+ krb5_data *state)
+{
+ state->length = 16;
+ state->data = (void *) malloc(16);
+ if (state->data == NULL)
+ return ENOMEM;
+ memset(state->data, 0, state->length);
+ return 0;
+}
+
+const struct krb5_enc_provider krb5int_enc_aes128 = {
+ 16,
+ 16, 16,
+ krb5int_aes_encrypt,
+ krb5int_aes_decrypt,
+ krb5int_aes_make_key,
+ krb5int_aes_init_state,
+ krb5int_default_free_state,
+ krb5int_aes_encrypt_iov,
+ krb5int_aes_decrypt_iov
+};
+
+const struct krb5_enc_provider krb5int_enc_aes256 = {
+ 16,
+ 32, 32,
+ krb5int_aes_encrypt,
+ krb5int_aes_decrypt,
+ krb5int_aes_make_key,
+ krb5int_aes_init_state,
+ krb5int_default_free_state,
+ krb5int_aes_encrypt_iov,
+ krb5int_aes_decrypt_iov
+};
+
diff --git a/src/lib/crypto/openssl/enc_provider/des.c b/src/lib/crypto/openssl/enc_provider/des.c
index b7a05db..4965c6e 100644
--- a/src/lib/crypto/openssl/enc_provider/des.c
+++ b/src/lib/crypto/openssl/enc_provider/des.c
@@ -35,7 +35,6 @@ validate_iov(const krb5_keyblock *key, const krb5_data *ivec,
for (i = 0, input_length = 0; i < num_data; i++) {
const krb5_crypto_iov *iov = &data[i];
-
if (ENCRYPT_IOV(iov))
input_length += iov->data.length;
}
@@ -54,12 +53,11 @@ static krb5_error_code
k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
const krb5_data *input, krb5_data *output)
{
- int ret = 0, tmp_len = 0;
- unsigned int tmp_buf_len = 0;
+ int ret = 0, tmp_len = 0;
+ unsigned int tmp_buf_len = 0;
unsigned char *keybuf = NULL;
unsigned char *tmp_buf = NULL;
- unsigned char iv[EVP_MAX_IV_LENGTH];
- EVP_CIPHER_CTX ciph_ctx;
+ EVP_CIPHER_CTX ciph_ctx;
ret = validate(key, ivec, input, output);
if (ret)
@@ -68,11 +66,6 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
keybuf=key->contents;
keybuf[key->length] = '\0';
- if ( ivec && ivec->data ) {
- memset(iv,0,sizeof(iv));
- memcpy(iv,ivec->data,ivec->length);
- }
-
tmp_buf_len = output->length*2;
tmp_buf=OPENSSL_malloc(tmp_buf_len);
if (!tmp_buf)
@@ -82,13 +75,13 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL, keybuf,
- (ivec && ivec->data) ? iv : NULL);
+ (ivec) ? (unsigned char*)ivec->data : NULL);
if (ret) {
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len,
(unsigned char *)input->data, input->length);
if (!ret || output->length < (unsigned int)tmp_len) {
- return KRB5_CRYPTO_INTERNAL;
+ ret = KRB5_CRYPTO_INTERNAL;
} else {
output->length = tmp_len;
ret = EVP_EncryptFinal_ex(&ciph_ctx, tmp_buf + tmp_len, &tmp_len);
@@ -97,13 +90,13 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
- if (ret)
+ if (ret == 1)
memcpy(output->data,tmp_buf, output->length);
memset(tmp_buf, 0, tmp_buf_len);
OPENSSL_free(tmp_buf);
- if (!ret)
+ if (ret != 1)
return KRB5_CRYPTO_INTERNAL;
return 0;
}
@@ -114,10 +107,9 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
const krb5_data *input, krb5_data *output)
{
/* key->enctype was checked by the caller */
- int ret = 0, tmp_len = 0;
+ int ret = 0, tmp_len = 0;
unsigned char *keybuf = NULL;
unsigned char *tmp_buf;
- unsigned char iv[EVP_MAX_IV_LENGTH];
EVP_CIPHER_CTX ciph_ctx;
ret = validate(key, ivec, input, output);
@@ -127,10 +119,6 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
keybuf=key->contents;
keybuf[key->length] = '\0';
- if ( ivec != NULL && ivec->data ){
- memset(iv,0,sizeof(iv));
- memcpy(iv,ivec->data,ivec->length);
- }
tmp_buf=OPENSSL_malloc(output->length);
if (!tmp_buf)
return ENOMEM;
@@ -139,7 +127,7 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL, keybuf,
- (ivec && ivec->data) ? iv : NULL);
+ (ivec) ? (unsigned char*)ivec->data : NULL);
if (ret) {
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
ret = EVP_DecryptUpdate(&ciph_ctx, tmp_buf, &tmp_len,
@@ -152,13 +140,13 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
- if (ret)
+ if (ret == 1)
memcpy(output->data,tmp_buf, output->length);
memset(tmp_buf,0,output->length);
OPENSSL_free(tmp_buf);
- if (!ret)
+ if ( ret != 1)
return KRB5_CRYPTO_INTERNAL;
return 0;
}
@@ -169,21 +157,21 @@ k5_des_encrypt_iov(const krb5_keyblock *key,
krb5_crypto_iov *data,
size_t num_data)
{
- int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH;
- EVP_CIPHER_CTX ciph_ctx;
- unsigned char *keybuf = NULL ;
- unsigned char iv[EVP_MAX_IV_LENGTH];
-
+ int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH;
+ int oblock_len = MIT_DES_BLOCK_LENGTH * num_data;
+ unsigned char *iblock = NULL, *oblock = NULL;
+ unsigned char *keybuf = NULL ;
struct iov_block_state input_pos, output_pos;
- int oblock_len = MIT_DES_BLOCK_LENGTH*num_data;
- unsigned char *iblock, *oblock;
+ EVP_CIPHER_CTX ciph_ctx;
iblock = OPENSSL_malloc(MIT_DES_BLOCK_LENGTH);
if (!iblock)
return ENOMEM;
oblock = OPENSSL_malloc(oblock_len);
- if (!oblock)
+ if (!oblock){
+ OPENSSL_free(iblock);
return ENOMEM;
+ }
IOV_BLOCK_STATE_INIT(&input_pos);
IOV_BLOCK_STATE_INIT(&output_pos);
@@ -195,19 +183,18 @@ k5_des_encrypt_iov(const krb5_keyblock *key,
if (ret)
return ret;
- if (ivec && ivec->data){
- memset(iv,0,sizeof(iv));
- memcpy(iv,ivec->data,ivec->length);
- }
-
memset(oblock, 0, oblock_len);
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL,
- keybuf, (ivec && ivec->data) ? iv : NULL);
- if (!ret)
+ keybuf, (ivec && ivec->data) ? (unsigned char*)ivec->data : NULL);
+ if (!ret){
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+ OPENSSL_free(iblock);
+ OPENSSL_free(oblock);
return KRB5_CRYPTO_INTERNAL;
+ }
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
@@ -229,11 +216,6 @@ k5_des_encrypt_iov(const krb5_keyblock *key,
if(ret)
ret = EVP_EncryptFinal_ex(&ciph_ctx, oblock+16, &tmp_len);
- if (ret) {
- if (ivec != NULL)
- memcpy(iv, oblock, MIT_DES_BLOCK_LENGTH);
- }
-
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
memset(iblock,0,sizeof(iblock));
@@ -241,7 +223,7 @@ k5_des_encrypt_iov(const krb5_keyblock *key,
OPENSSL_free(iblock);
OPENSSL_free(oblock);
- if (!ret)
+ if ( ret != 1)
return KRB5_CRYPTO_INTERNAL;
return 0;
}
@@ -252,21 +234,22 @@ k5_des_decrypt_iov(const krb5_keyblock *key,
krb5_crypto_iov *data,
size_t num_data)
{
- int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH;
- EVP_CIPHER_CTX ciph_ctx;
- unsigned char *keybuf = NULL ;
- unsigned char iv[EVP_MAX_IV_LENGTH];
-
+ int ret = 0;
+ int tmp_len = MIT_DES_BLOCK_LENGTH;
+ int oblock_len = MIT_DES_BLOCK_LENGTH*num_data;
+ unsigned char *iblock = NULL, *oblock = NULL;
+ unsigned char *keybuf = NULL;
struct iov_block_state input_pos, output_pos;
- int oblock_len = MIT_DES_BLOCK_LENGTH*num_data;
- unsigned char *iblock, *oblock;
+ EVP_CIPHER_CTX ciph_ctx;
iblock = OPENSSL_malloc(MIT_DES_BLOCK_LENGTH);
if (!iblock)
return ENOMEM;
oblock = OPENSSL_malloc(oblock_len);
- if (!oblock)
+ if (!oblock){
+ OPENSSL_free(iblock);
return ENOMEM;
+ }
IOV_BLOCK_STATE_INIT(&input_pos);
IOV_BLOCK_STATE_INIT(&output_pos);
@@ -278,19 +261,18 @@ k5_des_decrypt_iov(const krb5_keyblock *key,
if (ret)
return ret;
- if (ivec && ivec->data){
- memset(iv,0,sizeof(iv));
- memcpy(iv,ivec->data,ivec->length);
- }
-
memset(oblock, 0, oblock_len);
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL,
- keybuf, (ivec && ivec->data) ? iv : NULL);
- if (!ret)
+ keybuf, (ivec) ? (unsigned char*)ivec->data : NULL);
+ if (!ret){
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+ OPENSSL_free(iblock);
+ OPENSSL_free(oblock);
return KRB5_CRYPTO_INTERNAL;
+ }
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
@@ -315,11 +297,6 @@ k5_des_decrypt_iov(const krb5_keyblock *key,
if(ret)
ret = EVP_DecryptFinal_ex(&ciph_ctx, oblock+16, &tmp_len);
- if (ret) {
- if (ivec != NULL)
- memcpy(iv, oblock, MIT_DES_BLOCK_LENGTH);
- }
-
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
memset(iblock,0,sizeof(iblock));
@@ -327,7 +304,7 @@ k5_des_decrypt_iov(const krb5_keyblock *key,
OPENSSL_free(iblock);
OPENSSL_free(oblock);
- if (!ret)
+ if (ret != 1)
return KRB5_CRYPTO_INTERNAL;
return 0;
}
diff --git a/src/lib/crypto/openssl/enc_provider/des3.c b/src/lib/crypto/openssl/enc_provider/des3.c
index 4445af0..1dec8e2 100644
--- a/src/lib/crypto/openssl/enc_provider/des3.c
+++ b/src/lib/crypto/openssl/enc_provider/des3.c
@@ -36,7 +36,6 @@ validate_iov(const krb5_keyblock *key, const krb5_data *ivec,
for (i = 0, input_length = 0; i < num_data; i++) {
const krb5_crypto_iov *iov = &data[i];
-
if (ENCRYPT_IOV(iov))
input_length += iov->data.length;
}
@@ -55,12 +54,11 @@ static krb5_error_code
k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
const krb5_data *input, krb5_data *output)
{
- int ret = 0, tmp_len = 0;
- unsigned int tmp_buf_len = 0;
+ int ret = 0, tmp_len = 0;
+ unsigned int tmp_buf_len = 0;
unsigned char *keybuf = NULL;
unsigned char *tmp_buf = NULL;
- unsigned char iv[EVP_MAX_IV_LENGTH];
- EVP_CIPHER_CTX ciph_ctx;
+ EVP_CIPHER_CTX ciph_ctx;
ret = validate(key, ivec, input, output);
if (ret)
@@ -69,9 +67,6 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
keybuf=key->contents;
keybuf[key->length] = '\0';
- if (ivec && ivec->data) {
- memcpy(iv,ivec->data,ivec->length);
- }
tmp_buf_len = output->length * 2;
tmp_buf = OPENSSL_malloc(tmp_buf_len);
if (!tmp_buf)
@@ -80,7 +75,7 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL, keybuf,
- (ivec && ivec->data) ? iv : NULL);
+ (ivec) ? (unsigned char*)ivec->data : NULL);
if (ret) {
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len,
@@ -95,12 +90,13 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
- if (ret)
+ if (ret == 1)
memcpy(output->data,tmp_buf, output->length);
+
memset(tmp_buf, 0, tmp_buf_len);
OPENSSL_free(tmp_buf);
- if (!ret)
+ if (ret != 1)
return KRB5_CRYPTO_INTERNAL;
return 0;
@@ -111,11 +107,11 @@ static krb5_error_code
k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
const krb5_data *input, krb5_data *output)
{
- int ret = 0, tmp_len = 0;
- EVP_CIPHER_CTX ciph_ctx;
+ int ret = 0, tmp_len = 0;
+ unsigned int tmp_buf_len = 0;
unsigned char *keybuf = NULL;
unsigned char *tmp_buf = NULL;
- unsigned char iv[EVP_MAX_IV_LENGTH];
+ EVP_CIPHER_CTX ciph_ctx;
ret = validate(key, ivec, input, output);
if (ret)
@@ -124,24 +120,22 @@ k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
keybuf=key->contents;
keybuf[key->length] = '\0';
- if (ivec && ivec->data) {
- memset(iv,0,sizeof(iv));
- memcpy(iv,ivec->data,ivec->length);
- }
-
- tmp_buf=OPENSSL_malloc(output->length);
+ tmp_buf_len = output->length;
+ tmp_buf=OPENSSL_malloc(tmp_buf_len);
if (!tmp_buf)
return ENOMEM;
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL, keybuf,
- (ivec && ivec->data) ? iv: NULL);
+ (ivec) ? (unsigned char*)ivec->data: NULL);
if (ret) {
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
ret = EVP_DecryptUpdate(&ciph_ctx, tmp_buf, &tmp_len,
(unsigned char *)input->data, input->length);
- if (ret) {
+ if (!ret || output->length < (unsigned int)tmp_len) {
+ ret = KRB5_CRYPTO_INTERNAL;
+ } else {
output->length = tmp_len;
ret = EVP_DecryptFinal_ex(&ciph_ctx, tmp_buf+tmp_len, &tmp_len);
}
@@ -149,13 +143,13 @@ k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
- if (ret)
+ if (ret == 1)
memcpy(output->data,tmp_buf, output->length);
- memset(tmp_buf,0,output->length);
+ memset(tmp_buf,0,tmp_buf_len);
OPENSSL_free(tmp_buf);
- if (!ret)
+ if (ret != 1)
return KRB5_CRYPTO_INTERNAL;
return 0;
@@ -167,14 +161,13 @@ k5_des3_encrypt_iov(const krb5_keyblock *key,
krb5_crypto_iov *data,
size_t num_data)
{
- int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH;
- EVP_CIPHER_CTX ciph_ctx;
- unsigned char *keybuf = NULL ;
- unsigned char iv[EVP_MAX_IV_LENGTH];
-
+ int ret = 0;
+ int tmp_len = MIT_DES_BLOCK_LENGTH;
+ int oblock_len = MIT_DES_BLOCK_LENGTH*num_data;
+ unsigned char *iblock = NULL, *oblock = NULL;
+ unsigned char *keybuf = NULL;
struct iov_block_state input_pos, output_pos;
- int oblock_len = MIT_DES_BLOCK_LENGTH*num_data;
- unsigned char *iblock, *oblock;
+ EVP_CIPHER_CTX ciph_ctx;
ret = validate_iov(key, ivec, data, num_data);
if (ret)
@@ -184,8 +177,10 @@ k5_des3_encrypt_iov(const krb5_keyblock *key,
if (!iblock)
return ENOMEM;
oblock = OPENSSL_malloc(oblock_len);
- if (!oblock)
+ if (!oblock){
+ OPENSSL_free(iblock);
return ENOMEM;
+ }
IOV_BLOCK_STATE_INIT(&input_pos);
IOV_BLOCK_STATE_INIT(&output_pos);
@@ -193,19 +188,18 @@ k5_des3_encrypt_iov(const krb5_keyblock *key,
keybuf=key->contents;
keybuf[key->length] = '\0';
- if (ivec && ivec->data){
- memset(iv,0,sizeof(iv));
- memcpy(iv,ivec->data,ivec->length);
- }
-
memset(oblock, 0, oblock_len);
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL,
- keybuf, (ivec && ivec->data) ? iv : NULL);
- if (!ret)
+ keybuf, (ivec) ? (unsigned char*)ivec->data : NULL);
+ if (!ret){
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+ OPENSSL_free(iblock);
+ OPENSSL_free(oblock);
return KRB5_CRYPTO_INTERNAL;
+ }
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
@@ -229,11 +223,6 @@ k5_des3_encrypt_iov(const krb5_keyblock *key,
if(ret)
ret = EVP_EncryptFinal_ex(&ciph_ctx, oblock+input_pos.data_pos, &tmp_len);
- if (ret) {
- if (ivec != NULL)
- memcpy(iv, oblock, MIT_DES_BLOCK_LENGTH);
- }
-
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
memset(iblock,0,sizeof(iblock));
@@ -241,7 +230,7 @@ k5_des3_encrypt_iov(const krb5_keyblock *key,
OPENSSL_free(iblock);
OPENSSL_free(oblock);
- if (!ret)
+ if (ret != 1)
return KRB5_CRYPTO_INTERNAL;
return 0;
}
@@ -252,14 +241,13 @@ k5_des3_decrypt_iov(const krb5_keyblock *key,
krb5_crypto_iov *data,
size_t num_data)
{
- int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH;
- EVP_CIPHER_CTX ciph_ctx;
- unsigned char *keybuf = NULL ;
- unsigned char iv[EVP_MAX_IV_LENGTH];
-
+ int ret = 0;
+ int tmp_len = MIT_DES_BLOCK_LENGTH;
+ int oblock_len = MIT_DES_BLOCK_LENGTH * num_data;
+ unsigned char *iblock = NULL, *oblock = NULL;
+ unsigned char *keybuf = NULL ;
struct iov_block_state input_pos, output_pos;
- int oblock_len = MIT_DES_BLOCK_LENGTH*num_data;
- unsigned char *iblock, *oblock;
+ EVP_CIPHER_CTX ciph_ctx;
ret = validate_iov(key, ivec, data, num_data);
if (ret)
@@ -269,8 +257,10 @@ k5_des3_decrypt_iov(const krb5_keyblock *key,
if (!iblock)
return ENOMEM;
oblock = OPENSSL_malloc(oblock_len);
- if (!oblock)
+ if (!oblock){
+ OPENSSL_free(iblock);
return ENOMEM;
+ }
IOV_BLOCK_STATE_INIT(&input_pos);
IOV_BLOCK_STATE_INIT(&output_pos);
@@ -278,19 +268,18 @@ k5_des3_decrypt_iov(const krb5_keyblock *key,
keybuf=key->contents;
keybuf[key->length] = '\0';
- if (ivec && ivec->data){
- memset(iv,0,sizeof(iv));
- memcpy(iv,ivec->data,ivec->length);
- }
-
memset(oblock, 0, oblock_len);
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL,
- keybuf, (ivec && ivec->data) ? iv : NULL);
- if (!ret)
+ keybuf, (ivec) ? (unsigned char*)ivec->data : NULL);
+ if (!ret){
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+ OPENSSL_free(iblock);
+ OPENSSL_free(oblock);
return KRB5_CRYPTO_INTERNAL;
+ }
EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
@@ -315,11 +304,6 @@ k5_des3_decrypt_iov(const krb5_keyblock *key,
ret = EVP_DecryptFinal_ex(&ciph_ctx,
oblock + input_pos.data_pos, &tmp_len);
- if (ret) {
- if (ivec != NULL)
- memcpy(iv, oblock, MIT_DES_BLOCK_LENGTH);
- }
-
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
memset(iblock,0,sizeof(iblock));
@@ -327,7 +311,7 @@ k5_des3_decrypt_iov(const krb5_keyblock *key,
OPENSSL_free(iblock);
OPENSSL_free(oblock);
- if (!ret)
+ if (ret != 1)
return KRB5_CRYPTO_INTERNAL;
return 0;
}
diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
index 455a47f..ae2f58f 100644
--- a/src/lib/crypto/openssl/enc_provider/rc4.c
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
@@ -62,7 +62,7 @@ k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state,
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
- if (!ret)
+ if (ret != 1)
return KRB5_CRYPTO_INTERNAL;
output->length += tmp_len;
@@ -90,8 +90,10 @@ k5_arcfour_docrypt_iov(const krb5_keyblock *key,
EVP_CIPHER_CTX_init(&ciph_ctx);
ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_rc4(), NULL, keybuf, NULL);
- if (!ret)
- return -1;
+ if (!ret){
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+ return KRB5_CRYPTO_INTERNAL;
+ }
for (i = 0; i < num_data; i++) {
iov = &data[i];
@@ -112,7 +114,7 @@ k5_arcfour_docrypt_iov(const krb5_keyblock *key,
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
- if (!ret)
+ if (ret != 1)
return KRB5_CRYPTO_INTERNAL;
iov->data.length += tmp_len;