summaryrefslogtreecommitdiffstats
path: root/src/lib/crypto/openssl/enc_provider
diff options
context:
space:
mode:
authorZhanna Tsitkov <tsitkova@mit.edu>2009-09-03 18:33:13 +0000
committerZhanna Tsitkov <tsitkova@mit.edu>2009-09-03 18:33:13 +0000
commit65cc35ec82d56b8cd89751ddc5f68751271b985c (patch)
treed18357e0b500cf7f8c4b93ef4d67fe7485d50257 /src/lib/crypto/openssl/enc_provider
parent3e76c60f9f08b5f9f78d8e266d0109c85405c06f (diff)
downloadkrb5-65cc35ec82d56b8cd89751ddc5f68751271b985c.tar.gz
krb5-65cc35ec82d56b8cd89751ddc5f68751271b985c.tar.xz
krb5-65cc35ec82d56b8cd89751ddc5f68751271b985c.zip
Crypto modularity proj: OpemSSL crypto feed for hmac/md5/md4/sha1/rc4/des/des3(w/o iov)
bigredbutton: whitespace git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22709 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/crypto/openssl/enc_provider')
-rw-r--r--src/lib/crypto/openssl/enc_provider/deps50
-rw-r--r--src/lib/crypto/openssl/enc_provider/des.c271
-rw-r--r--src/lib/crypto/openssl/enc_provider/des3.c352
-rw-r--r--src/lib/crypto/openssl/enc_provider/enc_provider.h36
-rw-r--r--src/lib/crypto/openssl/enc_provider/rc4.c167
5 files changed, 876 insertions, 0 deletions
diff --git a/src/lib/crypto/openssl/enc_provider/deps b/src/lib/crypto/openssl/enc_provider/deps
new file mode 100644
index 0000000000..1d4dcbe975
--- /dev/null
+++ b/src/lib/crypto/openssl/enc_provider/deps
@@ -0,0 +1,50 @@
+#
+# Generated makefile dependencies follow.
+#
+des.so des.po $(OUTPRE)des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h \
+ $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \
+ $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
+ $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+ $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+ $(SRCTOP)/include/socket-utils.h $(srcdir)/../../builtin/des/des_int.h \
+ $(srcdir)/../../krb/aead.h $(srcdir)/../cksumtypes.h des.c \
+ enc_provider.h
+des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h \
+ $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \
+ $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
+ $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+ $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+ $(SRCTOP)/include/socket-utils.h $(srcdir)/../../builtin/des/des_int.h \
+ $(srcdir)/../../krb/aead.h $(srcdir)/../cksumtypes.h des3.c
+aes.so aes.po $(OUTPRE)aes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h \
+ $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \
+ $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
+ $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+ $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+ $(SRCTOP)/include/socket-utils.h $(srcdir)/../../builtin/aes/aes.h \
+ $(srcdir)/../../builtin/aes/uitypes.h $(srcdir)/../../krb/aead.h \
+ $(srcdir)/../cksumtypes.h aes.c enc_provider.h
+rc4.so rc4.po $(OUTPRE)rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/autoconf.h \
+ $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \
+ $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \
+ $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+ $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \
+ $(SRCTOP)/include/socket-utils.h $(srcdir)/../../builtin/arcfour/arcfour-int.h \
+ $(srcdir)/../../builtin/arcfour/arcfour.h $(srcdir)/../../krb/aead.h \
+ $(srcdir)/../cksumtypes.h enc_provider.h rc4.c
diff --git a/src/lib/crypto/openssl/enc_provider/des.c b/src/lib/crypto/openssl/enc_provider/des.c
new file mode 100644
index 0000000000..bc4313659b
--- /dev/null
+++ b/src/lib/crypto/openssl/enc_provider/des.c
@@ -0,0 +1,271 @@
+/*
+ */
+
+#include "k5-int.h"
+#include "des_int.h"
+#include "enc_provider.h"
+#include <aead.h>
+#include <openssl/evp.h>
+
+#define DES_BLOCK_SIZE 8
+#define DES_KEY_BYTES 7
+#define DES_KEY_LEN 8
+
+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;
+ EVP_CIPHER_CTX ciph_ctx;
+ unsigned char *keybuf = NULL;
+ unsigned char *tmp_buf = NULL;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ if (key->length != DES_KEY_LEN)
+ return(KRB5_BAD_KEYSIZE);
+ if ((input->length%8) != 0)
+ return(KRB5_BAD_MSIZE);
+ if (ivec && (ivec->length != 8))
+ return(KRB5_BAD_MSIZE);
+ if (input->length != output->length)
+ return(KRB5_BAD_MSIZE);
+
+ 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);
+ if (!tmp_buf)
+ return ENOMEM;
+ memset(tmp_buf,0,output->length);
+
+ EVP_CIPHER_CTX_init(&ciph_ctx);
+
+ ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL, keybuf,
+ (ivec && ivec->data) ? iv : 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 = tmp_len;
+ ret = EVP_EncryptFinal_ex(&ciph_ctx, tmp_buf + tmp_len, &tmp_len);
+ }
+ }
+
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+ if (ret)
+ memcpy(output->data,tmp_buf, output->length);
+
+ memset(tmp_buf,0,output->length);
+ OPENSSL_free(tmp_buf);
+
+ if (!ret)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+}
+
+static krb5_error_code
+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;
+ EVP_CIPHER_CTX ciph_ctx;
+ unsigned char *keybuf = NULL;
+ unsigned char *tmp_buf;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ if (key->length != DES_KEY_LEN)
+ return(KRB5_BAD_KEYSIZE);
+ if ((input->length%8) != 0)
+ return(KRB5_BAD_MSIZE);
+ if (ivec && (ivec->length != 8))
+ return(KRB5_BAD_MSIZE);
+ if (input->length != output->length)
+ return(KRB5_BAD_MSIZE);
+
+ 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;
+ memset(tmp_buf,0,output->length);
+
+ EVP_CIPHER_CTX_init(&ciph_ctx);
+
+ ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL, keybuf,
+ (ivec && ivec->data) ? iv : 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) {
+ output->length = tmp_len;
+ ret = EVP_DecryptFinal_ex(&ciph_ctx, tmp_buf+tmp_len, &tmp_len);
+ }
+ }
+
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+ if (ret)
+ memcpy(output->data,tmp_buf, output->length);
+
+ memset(tmp_buf,0,output->length );
+ OPENSSL_free(tmp_buf);
+
+ if (!ret)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+}
+
+static krb5_error_code
+k5_des_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+ if (key->length != DES_KEY_LEN)
+ return(KRB5_BAD_KEYSIZE);
+ if (randombits->length != 7)
+ return(KRB5_CRYPTO_INTERNAL);
+
+ key->magic = KV5M_KEYBLOCK;
+
+ /* take the seven bytes, move them around into the top 7 bits of the
+ 8 key bytes, then compute the parity bits */
+
+ memcpy(key->contents, randombits->data, randombits->length);
+ key->contents[7] = (((key->contents[0]&1)<<1) | ((key->contents[1]&1)<<2) |
+ ((key->contents[2]&1)<<3) | ((key->contents[3]&1)<<4) |
+ ((key->contents[4]&1)<<5) | ((key->contents[5]&1)<<6) |
+ ((key->contents[6]&1)<<7));
+
+ mit_des_fixup_key_parity(key->contents);
+
+ return(0);
+}
+
+static krb5_error_code
+k5_des_encrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ int ret = 0, tmp_len = 0;
+ unsigned int i = 0;
+ EVP_CIPHER_CTX ciph_ctx;
+ unsigned char *keybuf = NULL ;
+ krb5_crypto_iov *iov = NULL;
+ unsigned char *tmp_buf = NULL;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ if (ivec && ivec->data){
+ memset(iv,0,sizeof(iv));
+ memcpy(iv,ivec->data,ivec->length);
+ }
+
+ EVP_CIPHER_CTX_init(&ciph_ctx);
+
+ ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL,
+ keybuf, (ivec && ivec->data) ? iv : NULL);
+ if (!ret)
+ return KRB5_CRYPTO_INTERNAL;
+
+ for (i = 0; i < num_data; i++) {
+ iov = &data[i];
+ if (iov->data.length <= 0) break;
+ tmp_len = iov->data.length;
+
+ if (ENCRYPT_DATA_IOV(iov)) {
+ tmp_buf=(unsigned char *)iov->data.data;
+ ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len,
+ (unsigned char *)iov->data.data, iov->data.length);
+ if (!ret) break;
+ iov->data.length = tmp_len;
+ }
+ }
+ if(ret)
+ ret = EVP_EncryptFinal_ex(&ciph_ctx, (unsigned char *)tmp_buf, &tmp_len);
+
+ if (ret)
+ iov->data.length += tmp_len;
+
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+ if (!ret)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+
+}
+
+static krb5_error_code
+k5_des_decrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ int ret = 0, tmp_len = 0;
+ unsigned int i = 0;
+ EVP_CIPHER_CTX ciph_ctx;
+ unsigned char *keybuf = NULL ;
+ krb5_crypto_iov *iov = NULL;
+ unsigned char *tmp_buf = NULL;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ if (ivec && ivec->data){
+ memset(iv,0,sizeof(iv));
+ memcpy(iv,ivec->data,ivec->length);
+ }
+
+ ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_cbc(), NULL,
+ keybuf, (ivec && ivec->data) ? iv : NULL);
+ if (!ret)
+ return KRB5_CRYPTO_INTERNAL;
+
+ for (i = 0; i < num_data; i++) {
+ iov = &data[i];
+ if (iov->data.length <= 0) break;
+ tmp_len = iov->data.length;
+
+ if (ENCRYPT_DATA_IOV(iov)) {
+ tmp_buf=(unsigned char *)iov->data.data;
+ ret = EVP_DecryptUpdate(&ciph_ctx, tmp_buf, &tmp_len,
+ (unsigned char *)iov->data.data, iov->data.length);
+ if (!ret) break;
+ iov->data.length = tmp_len;
+ }
+ }
+ if(ret)
+ ret = EVP_DecryptFinal_ex(&ciph_ctx, (unsigned char *)tmp_buf, &tmp_len);
+
+ if (ret)
+ iov->data.length += tmp_len;
+
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+ if (!ret)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+}
+
+const struct krb5_enc_provider krb5int_enc_des = {
+ DES_BLOCK_SIZE,
+ DES_KEY_BYTES, DES_KEY_LEN,
+ k5_des_encrypt,
+ k5_des_decrypt,
+ k5_des_make_key,
+ krb5int_des_init_state,
+ krb5int_default_free_state,
+ k5_des_encrypt_iov,
+ k5_des_decrypt_iov
+};
+
diff --git a/src/lib/crypto/openssl/enc_provider/des3.c b/src/lib/crypto/openssl/enc_provider/des3.c
new file mode 100644
index 0000000000..1cc67483df
--- /dev/null
+++ b/src/lib/crypto/openssl/enc_provider/des3.c
@@ -0,0 +1,352 @@
+/*
+ */
+
+#include "k5-int.h"
+#include "des_int.h"
+#include <aead.h>
+#include <openssl/evp.h>
+
+
+#define DES_BLOCK_SIZE 8
+#define DES3_KEY_BYTES 21
+#define DES3_KEY_LEN 24
+
+static krb5_error_code
+validate(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_data *input, const krb5_data *output)
+{
+ mit_des3_key_schedule schedule;
+
+ /* key->enctype was checked by the caller */
+
+ if (key->length != DES3_KEY_LEN)
+ return(KRB5_BAD_KEYSIZE);
+ if ((input->length%DES_BLOCK_SIZE) != 0)
+ return(KRB5_BAD_MSIZE);
+ if (ivec && (ivec->length != 8))
+ return(KRB5_BAD_MSIZE);
+ if (input->length != output->length)
+ return(KRB5_BAD_MSIZE);
+
+ switch (mit_des3_key_sched(*(mit_des3_cblock *)key->contents,
+ schedule)) {
+ case -1:
+ return(KRB5DES_BAD_KEYPAR);
+ case -2:
+ return(KRB5DES_WEAK_KEY);
+ }
+ return 0;
+}
+
+static krb5_error_code
+validate_iov(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_crypto_iov *data, size_t num_data)
+{
+ size_t i, input_length;
+ mit_des3_key_schedule schedule;
+
+ 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;
+ }
+
+ if (key->length != DES3_KEY_LEN)
+ return(KRB5_BAD_KEYSIZE);
+ if ((input_length%DES_BLOCK_SIZE) != 0)
+ return(KRB5_BAD_MSIZE);
+ if (ivec && (ivec->length != 8))
+ return(KRB5_BAD_MSIZE);
+
+ switch (mit_des3_key_sched(*(mit_des3_cblock *)key->contents,
+ schedule)) {
+ case -1:
+ return(KRB5DES_BAD_KEYPAR);
+ case -2:
+ return(KRB5DES_WEAK_KEY);
+ }
+ return 0;
+}
+
+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;
+ EVP_CIPHER_CTX ciph_ctx;
+ unsigned char *keybuf = NULL;
+ unsigned char *tmp_buf = NULL;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ ret = validate(key, ivec, input, output);
+ if (ret)
+ return ret;
+
+ 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);
+ if (!tmp_buf)
+ return ENOMEM;
+
+ 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) {
+ 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 = tmp_len;
+ ret = EVP_EncryptFinal_ex(&ciph_ctx, tmp_buf+tmp_len, &tmp_len);
+ }
+ }
+
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+ if (ret)
+ memcpy(output->data,tmp_buf, output->length);
+ memset(tmp_buf,0,output->length);
+ OPENSSL_free(tmp_buf);
+
+ if (!ret)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+
+}
+
+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;
+ unsigned char *keybuf = NULL;
+ unsigned char *tmp_buf = NULL;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ ret = validate(key, ivec, input, output);
+ if (ret)
+ return ret;
+
+ 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);
+ 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);
+ 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) {
+ output->length = tmp_len;
+ ret = EVP_DecryptFinal_ex(&ciph_ctx, tmp_buf+tmp_len, &tmp_len);
+ }
+ }
+
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+ if (ret)
+ memcpy(output->data,tmp_buf, output->length);
+
+ memset(tmp_buf,0,output->length);
+ OPENSSL_free(tmp_buf);
+
+ if (!ret)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+
+}
+
+static krb5_error_code
+k5_des3_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+ int i;
+
+ if (key->length != DES3_KEY_LEN)
+ return(KRB5_BAD_KEYSIZE);
+ if (randombits->length != DES3_KEY_BYTES)
+ return(KRB5_CRYPTO_INTERNAL);
+
+ key->magic = KV5M_KEYBLOCK;
+
+ /* take the seven bytes, move them around into the top 7 bits of the
+ 8 key bytes, then compute the parity bits. Do this three times. */
+
+ for (i=0; i<3; i++) {
+ memcpy(key->contents+i*8, randombits->data+i*7, 7);
+ key->contents[i*8+7] = (((key->contents[i*8]&1)<<1) |
+ ((key->contents[i*8+1]&1)<<2) |
+ ((key->contents[i*8+2]&1)<<3) |
+ ((key->contents[i*8+3]&1)<<4) |
+ ((key->contents[i*8+4]&1)<<5) |
+ ((key->contents[i*8+5]&1)<<6) |
+ ((key->contents[i*8+6]&1)<<7));
+
+ mit_des_fixup_key_parity(key->contents+i*8);
+ }
+
+ return(0);
+}
+
+static krb5_error_code
+validate_and_schedule_iov(const krb5_keyblock *key, const krb5_data *ivec,
+ const krb5_crypto_iov *data, size_t num_data,
+ mit_des3_key_schedule *schedule)
+{
+ size_t i, input_length;
+
+ 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;
+ }
+
+ if (key->length != 24)
+ return(KRB5_BAD_KEYSIZE);
+ if ((input_length%8) != 0)
+ return(KRB5_BAD_MSIZE);
+ if (ivec && (ivec->length != 8))
+ return(KRB5_BAD_MSIZE);
+
+ switch (mit_des3_key_sched(*(mit_des3_cblock *)key->contents,
+ *schedule)) {
+ case -1:
+ return(KRB5DES_BAD_KEYPAR);
+ case -2:
+ return(KRB5DES_WEAK_KEY);
+ }
+ return 0;
+}
+
+static krb5_error_code
+k5_des3_encrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+#if 0
+ int ret = 0, tmp_len = 0;
+ unsigned int i = 0;
+ EVP_CIPHER_CTX ciph_ctx;
+ unsigned char *keybuf = NULL ;
+ krb5_crypto_iov *iov = NULL;
+ unsigned char *tmp_buf = NULL;
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ ret = validate_iov(key, ivec, data, num_data);
+ if (ret)
+ return ret;
+
+ if (ivec && ivec->data){
+ memset(iv,0,sizeof(iv));
+ memcpy(iv,ivec->data,ivec->length);
+ }
+
+
+ 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)
+ return KRB5_CRYPTO_INTERNAL;
+
+ for (i = 0; i < num_data; i++) {
+ iov = &data[i];
+ if (iov->data.length <= 0) break;
+ tmp_len = iov->data.length;
+
+ if (ENCRYPT_IOV(iov)) {
+ tmp_buf=(unsigned char *)iov->data.data;
+ ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len,
+ (unsigned char *)iov->data.data, iov->data.length);
+ if (!ret) break;
+ iov->data.length = tmp_len;
+ }
+ }
+ if(ret)
+ ret = EVP_EncryptFinal_ex(&ciph_ctx, (unsigned char *)tmp_buf, &tmp_len);
+
+ if (ret)
+ iov->data.length += tmp_len;
+
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+ if (!ret)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+#endif
+
+//#if 0
+ mit_des3_key_schedule schedule;
+ krb5_error_code err;
+
+ err = validate_and_schedule_iov(key, ivec, data, num_data, &schedule);
+ if (err)
+ return err;
+
+ /* this has a return value, but the code always returns zero */
+ krb5int_des3_cbc_encrypt_iov(data, num_data,
+ schedule[0], schedule[1], schedule[2],
+ ivec != NULL ? (unsigned char *) ivec->data : NULL);
+
+ zap(schedule, sizeof(schedule));
+ return(0);
+//#endif
+}
+
+static krb5_error_code
+k5_des3_decrypt_iov(const krb5_keyblock *key,
+ const krb5_data *ivec,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ mit_des3_key_schedule schedule;
+ krb5_error_code err;
+
+ err = validate_and_schedule_iov(key, ivec, data, num_data, &schedule);
+ if (err)
+ return err;
+
+ /* this has a return value, but the code always returns zero */
+ krb5int_des3_cbc_decrypt_iov(data, num_data,
+ schedule[0], schedule[1], schedule[2],
+ ivec != NULL ? (unsigned char *) ivec->data : NULL);
+
+ zap(schedule, sizeof(schedule));
+
+ return(0);
+}
+
+const struct krb5_enc_provider krb5int_enc_des3 = {
+ DES_BLOCK_SIZE,
+ DES3_KEY_BYTES, DES3_KEY_LEN,
+ k5_des3_encrypt,
+ k5_des3_decrypt,
+ k5_des3_make_key,
+ krb5int_des_init_state,
+ krb5int_default_free_state,
+ k5_des3_encrypt_iov,
+ k5_des3_decrypt_iov
+};
+
diff --git a/src/lib/crypto/openssl/enc_provider/enc_provider.h b/src/lib/crypto/openssl/enc_provider/enc_provider.h
new file mode 100644
index 0000000000..d46e1b4464
--- /dev/null
+++ b/src/lib/crypto/openssl/enc_provider/enc_provider.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "k5-int.h"
+
+extern const struct krb5_enc_provider krb5int_enc_des;
+extern const struct krb5_enc_provider krb5int_enc_des3;
+extern const struct krb5_enc_provider krb5int_enc_arcfour;
+extern const struct krb5_enc_provider krb5int_enc_aes128;
+extern const struct krb5_enc_provider krb5int_enc_aes256;
+extern const struct krb5_enc_provider krb5int_enc_aes128_ctr;
+extern const struct krb5_enc_provider krb5int_enc_aes256_ctr;
+
diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c
new file mode 100644
index 0000000000..b82af5247a
--- /dev/null
+++ b/src/lib/crypto/openssl/enc_provider/rc4.c
@@ -0,0 +1,167 @@
+/* arcfour.c
+ *
+ * #include STD_DISCLAIMER
+ */
+
+#include "k5-int.h"
+#include "arcfour-int.h"
+#include "enc_provider.h"
+#include <aead.h>
+#include <openssl/evp.h>
+
+#define RC4_KEY_SIZE 16
+#define RC4_BLOCK_SIZE 1
+
+/* Interface layer to kerb5 crypto layer */
+static krb5_error_code
+k5_arcfour_docrypt(const krb5_keyblock *, const krb5_data *,
+ const krb5_data *, krb5_data *);
+
+/* from a random bitstrem, construct a key */
+static krb5_error_code
+k5_arcfour_make_key(const krb5_data *, krb5_keyblock *);
+
+static krb5_error_code
+k5_arcfour_free_state ( krb5_data *state);
+static krb5_error_code
+k5_arcfour_init_state (const krb5_keyblock *key,
+ krb5_keyusage keyusage, krb5_data *new_state);
+
+/* The workhorse of the arcfour system, this impliments the cipher */
+static krb5_error_code
+k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state,
+ const krb5_data *input, krb5_data *output)
+{
+ int ret = 0, tmp_len = 0;
+ unsigned char *keybuf = NULL;
+ unsigned char *tmp_buf = NULL;
+ EVP_CIPHER_CTX ciph_ctx;
+
+ if (key->length != RC4_KEY_SIZE)
+ return(KRB5_BAD_KEYSIZE);
+
+ if (input->length != output->length)
+ return(KRB5_BAD_MSIZE);
+
+ keybuf=key->contents;
+ keybuf[key->length] = '\0';
+
+ EVP_CIPHER_CTX_init(&ciph_ctx);
+ ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_rc4(), NULL, keybuf, NULL);
+ if (ret) {
+ tmp_buf=(unsigned char *)output->data;
+ ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf, &tmp_len, (unsigned char *)input->data, input->length);
+ output->length = tmp_len;
+ }
+ if (ret) {
+ tmp_buf += tmp_len;
+ ret = EVP_EncryptFinal_ex(&ciph_ctx, tmp_buf, &tmp_len);
+ }
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+ output->length += tmp_len;
+
+ if (!ret)
+ return KRB5_CRYPTO_INTERNAL;
+ return 0;
+}
+
+
+/* In-place decryption */
+static krb5_error_code
+k5_arcfour_docrypt_iov(const krb5_keyblock *key,
+ const krb5_data *state,
+ krb5_crypto_iov *data,
+ size_t num_data)
+{
+ size_t i;
+ int ret = 0, tmp_len = 0;
+ EVP_CIPHER_CTX ciph_ctx;
+ unsigned char *keybuf = NULL ;
+ krb5_crypto_iov *iov = NULL;
+ unsigned char *tmp_buf = NULL;
+
+ keybuf=key->contents;
+ keybuf[key->length] = '\0';
+
+ EVP_CIPHER_CTX_init(&ciph_ctx);
+
+ ret = EVP_EncryptInit_ex(&ciph_ctx, EVP_rc4(), NULL, keybuf, NULL);
+ if (!ret)
+ return -1;
+
+ for (i = 0; i < num_data; i++) {
+ iov = &data[i];
+ if (iov->data.length <= 0) break;
+ tmp_len = iov->data.length;
+
+ if (ENCRYPT_IOV(iov)) {
+ tmp_buf=(unsigned char *)iov->data.data;
+ ret = EVP_EncryptUpdate(&ciph_ctx,
+ tmp_buf, &tmp_len,
+ (unsigned char *)iov->data.data, iov->data.length);
+ if (!ret) break;
+ iov->data.length = tmp_len;
+ }
+ }
+ if(ret)
+ ret = EVP_EncryptFinal_ex(&ciph_ctx, (unsigned char *)tmp_buf, &tmp_len);
+ if (ret)
+ iov->data.length += tmp_len;
+ EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
+ if (!ret)
+ return -1;
+ return 0;
+}
+
+
+static krb5_error_code
+k5_arcfour_make_key(const krb5_data *randombits, krb5_keyblock *key)
+{
+ if (key->length != RC4_KEY_SIZE)
+ return(KRB5_BAD_KEYSIZE);
+ if (randombits->length != RC4_KEY_SIZE)
+ return(KRB5_CRYPTO_INTERNAL);
+
+ key->magic = KV5M_KEYBLOCK;
+
+ memcpy(key->contents, randombits->data, randombits->length);
+
+ return(0);
+}
+
+static krb5_error_code
+k5_arcfour_free_state ( krb5_data *state)
+{
+ return 0; /* not implemented */
+}
+
+static krb5_error_code
+k5_arcfour_init_state (const krb5_keyblock *key,
+ krb5_keyusage keyusage, krb5_data *new_state)
+{
+ return 0; /* not implemented */
+
+}
+
+/* Since the arcfour cipher is identical going forwards and backwards,
+ we just call "docrypt" directly
+*/
+const struct krb5_enc_provider krb5int_enc_arcfour = {
+ /* This seems to work... although I am not sure what the
+ implications are in other places in the kerberos library */
+ RC4_BLOCK_SIZE,
+ /* Keysize is arbitrary in arcfour, but the constraints of the
+ system, and to attempt to work with the MSFT system forces us
+ to 16byte/128bit. Since there is no parity in the key, the
+ byte and length are the same. */
+ RC4_KEY_SIZE, RC4_KEY_SIZE,
+ k5_arcfour_docrypt,
+ k5_arcfour_docrypt,
+ k5_arcfour_make_key,
+ k5_arcfour_init_state, /*xxx not implemented */
+ k5_arcfour_free_state, /*xxx not implemented */
+ k5_arcfour_docrypt_iov,
+ k5_arcfour_docrypt_iov
+};
+