]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Merge trunk changes from r22791 to r22833 to enc-perf branch
authorGreg Hudson <ghudson@mit.edu>
Fri, 2 Oct 2009 15:33:56 +0000 (15:33 +0000)
committerGreg Hudson <ghudson@mit.edu>
Fri, 2 Oct 2009 15:33:56 +0000 (15:33 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/enc-perf@22834 dc483132-0cff-0310-8789-dd5450dbe970

25 files changed:
src/lib/crypto/builtin/hash_provider/Makefile.in
src/lib/crypto/openssl/arcfour/arcfour-int.h [new file with mode: 0644]
src/lib/crypto/openssl/arcfour/arcfour.c [new file with mode: 0644]
src/lib/crypto/openssl/arcfour/arcfour.h [new file with mode: 0644]
src/lib/crypto/openssl/arcfour/arcfour_aead.c [new file with mode: 0644]
src/lib/crypto/openssl/arcfour/arcfour_s2k.c [new file with mode: 0644]
src/lib/crypto/openssl/des/afsstring2key.c [new file with mode: 0644]
src/lib/crypto/openssl/des/d3_aead.c [new file with mode: 0644]
src/lib/crypto/openssl/des/d3_cbc.c [new file with mode: 0644]
src/lib/crypto/openssl/des/d3_kysched.c [new file with mode: 0644]
src/lib/crypto/openssl/des/des_int.h [new file with mode: 0644]
src/lib/crypto/openssl/des/f_aead.c [new file with mode: 0644]
src/lib/crypto/openssl/des/f_cbc.c [new file with mode: 0644]
src/lib/crypto/openssl/des/f_cksum.c [new file with mode: 0644]
src/lib/crypto/openssl/des/f_parity.c [new file with mode: 0644]
src/lib/crypto/openssl/des/f_sched.c [new file with mode: 0644]
src/lib/crypto/openssl/des/f_tables.c [new file with mode: 0644]
src/lib/crypto/openssl/des/f_tables.h [new file with mode: 0644]
src/lib/crypto/openssl/des/key_sched.c [new file with mode: 0644]
src/lib/crypto/openssl/des/string2key.c [new file with mode: 0644]
src/lib/crypto/openssl/des/weak_key.c [new file with mode: 0644]
src/lib/crypto/openssl/enc_provider/aes.c [new file with mode: 0644]
src/lib/crypto/openssl/enc_provider/des.c
src/lib/crypto/openssl/enc_provider/des3.c
src/lib/crypto/openssl/enc_provider/rc4.c

index 75b3d1b0cbb2ae3f082e61855d0ade2318982cc7..a901d1175ef0fcaf873fe96dd84a2b413909ae2a 100644 (file)
@@ -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 (file)
index 0000000..d9db0be
--- /dev/null
@@ -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 (file)
index 0000000..687f276
--- /dev/null
@@ -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 (file)
index 0000000..be408fe
--- /dev/null
@@ -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 (file)
index 0000000..cff7d66
--- /dev/null
@@ -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 (file)
index 0000000..41053ed
--- /dev/null
@@ -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 (file)
index 0000000..031db58
--- /dev/null
@@ -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 (file)
index 0000000..cd99886
--- /dev/null
@@ -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 (file)
index 0000000..98caab5
--- /dev/null
@@ -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 (file)
index 0000000..fb42e79
--- /dev/null
@@ -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 (file)
index 0000000..fd2024a
--- /dev/null
@@ -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 (file)
index 0000000..2046475
--- /dev/null
@@ -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 (file)
index 0000000..55b648f
--- /dev/null
@@ -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 (file)
index 0000000..c49c8fd
--- /dev/null
@@ -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 (file)
index 0000000..1a83db6
--- /dev/null
@@ -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 (file)
index 0000000..e833132
--- /dev/null
@@ -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 (file)
index 0000000..a8d161d
--- /dev/null
@@ -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 (file)
index 0000000..af20cd5
--- /dev/null
@@ -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 (file)
index 0000000..1007ec9
--- /dev/null
@@ -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 (file)
index 0000000..775a153
--- /dev/null
@@ -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 (file)
index 0000000..7f97083
--- /dev/null
@@ -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 (file)
index 0000000..c167818
--- /dev/null
@@ -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
+};
+
index b7a05db7c34df0db6541842282fbdd873ee2b10d..4965c6e6fa4dd78e07b478960274bcf7cde62234 100644 (file)
@@ -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;
 }
index 4445af0d8f10e3d83c4a0b0c7b7f2e8c8ae5e693..1dec8e27e21f928603a7d4b6cb3d28d7c757d3a1 100644 (file)
@@ -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;
 }
index 455a47faaf4aa69265d2b0f4a52958cd6e1a0057..ae2f58f40690295507375a3cb91e4faf2e950f26 100644 (file)
@@ -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;