diff options
| author | Zhanna Tsitkov <tsitkova@mit.edu> | 2009-09-03 18:33:13 +0000 |
|---|---|---|
| committer | Zhanna Tsitkov <tsitkova@mit.edu> | 2009-09-03 18:33:13 +0000 |
| commit | 65cc35ec82d56b8cd89751ddc5f68751271b985c (patch) | |
| tree | d18357e0b500cf7f8c4b93ef4d67fe7485d50257 /src/lib/crypto/openssl/enc_provider | |
| parent | 3e76c60f9f08b5f9f78d8e266d0109c85405c06f (diff) | |
| download | krb5-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/deps | 50 | ||||
| -rw-r--r-- | src/lib/crypto/openssl/enc_provider/des.c | 271 | ||||
| -rw-r--r-- | src/lib/crypto/openssl/enc_provider/des3.c | 352 | ||||
| -rw-r--r-- | src/lib/crypto/openssl/enc_provider/enc_provider.h | 36 | ||||
| -rw-r--r-- | src/lib/crypto/openssl/enc_provider/rc4.c | 167 |
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 +}; + |
