Crypto modularity proj: Updated IOV crypto
authorZhanna Tsitkov <tsitkova@mit.edu>
Fri, 25 Sep 2009 15:12:27 +0000 (15:12 +0000)
committerZhanna Tsitkov <tsitkova@mit.edu>
Fri, 25 Sep 2009 15:12:27 +0000 (15:12 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22786 dc483132-0cff-0310-8789-dd5450dbe970

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 3aed648fd373a28be1e1f481a86424c9271ebeee..b7a05db7c34df0db6541842282fbdd873ee2b10d 100644 (file)
@@ -1,34 +1,69 @@
-/*
+/* lib/crypto/openssl/enc_provider/des.c
  */
 
 #include "k5-int.h"
-#include "des_int.h"
-#include "enc_provider.h"
 #include <aead.h>
 #include <rand2key.h>
 #include <openssl/evp.h>
+#include "des_int.h"
 
 #define DES_BLOCK_SIZE  8
 #define DES_KEY_BYTES   7
 
+static krb5_error_code
+validate(const krb5_keyblock *key, const krb5_data *ivec,
+                      const krb5_data *input, const krb5_data *output)
+{
+    /* key->enctype was checked by the caller */
+    if (key->length != KRB5_MIT_DES_KEYSIZE)
+        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);
+
+    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;
+
+    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 != KRB5_MIT_DES3_KEYSIZE)
+        return(KRB5_BAD_KEYSIZE);
+    if ((input_length%DES_BLOCK_SIZE) != 0)
+        return(KRB5_BAD_MSIZE);
+    if (ivec && (ivec->length != 8))
+        return(KRB5_BAD_MSIZE);
+
+    return 0;
+}
+
 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 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;
 
-    if (key->length != KRB5_MIT_DES_KEYSIZE)
-        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);
+    ret = validate(key, ivec, input, output);
+    if (ret)
+        return ret;
 
     keybuf=key->contents;
     keybuf[key->length] = '\0';
@@ -38,7 +73,8 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
         memcpy(iv,ivec->data,ivec->length);
     }
 
-    tmp_buf=OPENSSL_malloc(output->length);
+    tmp_buf_len = output->length*2;
+    tmp_buf=OPENSSL_malloc(tmp_buf_len);
     if (!tmp_buf)
         return ENOMEM;
     memset(tmp_buf,0,output->length);
@@ -51,7 +87,9 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
         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) {
+        if (!ret || output->length < (unsigned int)tmp_len) {
+            return KRB5_CRYPTO_INTERNAL;
+        } else {
             output->length = tmp_len;
             ret = EVP_EncryptFinal_ex(&ciph_ctx, tmp_buf + tmp_len, &tmp_len);
         }
@@ -62,7 +100,7 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
     if (ret)
         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)
@@ -70,25 +108,21 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
     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];
+    EVP_CIPHER_CTX  ciph_ctx;
 
-    if (key->length != KRB5_MIT_DES_KEYSIZE)
-        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);
+    ret = validate(key, ivec, input, output);
+    if (ret)
+        return ret;
 
     keybuf=key->contents;
     keybuf[key->length] = '\0';
@@ -97,7 +131,6 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
         memset(iv,0,sizeof(iv));
         memcpy(iv,ivec->data,ivec->length);
     }
-
     tmp_buf=OPENSSL_malloc(output->length);
     if (!tmp_buf)
         return ENOMEM;
@@ -122,7 +155,7 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
     if (ret)
         memcpy(output->data,tmp_buf, output->length);
 
-    memset(tmp_buf,0,output->length );
+    memset(tmp_buf,0,output->length);
     OPENSSL_free(tmp_buf);
 
     if (!ret)
@@ -136,18 +169,38 @@ k5_des_encrypt_iov(const krb5_keyblock *key,
             krb5_crypto_iov *data,
             size_t num_data)
 {
-    int ret = 0, tmp_len = 0;
-    unsigned int i = 0;
+    int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH;
     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){
+    struct iov_block_state input_pos, output_pos;
+    int oblock_len = MIT_DES_BLOCK_LENGTH*num_data;
+    unsigned char  *iblock, *oblock;
+
+    iblock = OPENSSL_malloc(MIT_DES_BLOCK_LENGTH);
+    if (!iblock)
+        return ENOMEM;
+    oblock = OPENSSL_malloc(oblock_len);
+    if (!oblock)
+        return ENOMEM;
+
+    IOV_BLOCK_STATE_INIT(&input_pos);
+    IOV_BLOCK_STATE_INIT(&output_pos);
+
+    keybuf=key->contents;
+    keybuf[key->length] = '\0';
+
+    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);
-     }
+    }
+
+    memset(oblock, 0, oblock_len);
 
     EVP_CIPHER_CTX_init(&ciph_ctx);
 
@@ -156,31 +209,41 @@ k5_des_encrypt_iov(const krb5_keyblock *key,
     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;
-        }
+    EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+
+    for (;;) {
+
+        if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH, data, num_data, &input_pos))
+            break;
+
+        if (input_pos.iov_pos == num_data)
+            break;
+
+        ret = EVP_EncryptUpdate(&ciph_ctx, oblock, &tmp_len,
+                                (unsigned char *)iblock, input_pos.data_pos);
+        if (!ret) break;
+
+        krb5int_c_iov_put_block(data, num_data, oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
     }
+
     if(ret)
-        ret = EVP_EncryptFinal_ex(&ciph_ctx, (unsigned char *)tmp_buf, &tmp_len);
+        ret = EVP_EncryptFinal_ex(&ciph_ctx, oblock+16, &tmp_len);
 
-    if (ret)
-        iov->data.length += 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));
+    memset(oblock,0,sizeof(oblock));
+    OPENSSL_free(iblock);
+    OPENSSL_free(oblock);
+
     if (!ret)
         return KRB5_CRYPTO_INTERNAL;
     return 0;
-
 }
 
 static krb5_error_code
@@ -189,45 +252,81 @@ k5_des_decrypt_iov(const krb5_keyblock *key,
            krb5_crypto_iov *data,
            size_t num_data)
 {
-    int ret = 0, tmp_len = 0;
-    unsigned int i = 0;
+    int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH;
     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){
+    struct iov_block_state input_pos, output_pos;
+    int oblock_len = MIT_DES_BLOCK_LENGTH*num_data;
+    unsigned char  *iblock, *oblock;
+
+    iblock = OPENSSL_malloc(MIT_DES_BLOCK_LENGTH);
+    if (!iblock)
+        return ENOMEM;
+    oblock = OPENSSL_malloc(oblock_len);
+    if (!oblock)
+        return ENOMEM;
+
+    IOV_BLOCK_STATE_INIT(&input_pos);
+    IOV_BLOCK_STATE_INIT(&output_pos);
+
+    keybuf=key->contents;
+    keybuf[key->length] = '\0';
+
+    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);
-     }
+    }
+
+    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)
         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;
-        }
+    EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+
+    for (;;) {
+
+        if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH,
+                                     data, num_data, &input_pos))
+            break;
+
+        if (input_pos.iov_pos == num_data)
+            break;
+
+        ret = EVP_DecryptUpdate(&ciph_ctx, oblock, &tmp_len,
+                                (unsigned char *)iblock,
+                                input_pos.data_pos);
+        if (!ret) break;
+
+        krb5int_c_iov_put_block(data, num_data, oblock,
+                                MIT_DES_BLOCK_LENGTH, &output_pos);
     }
+
     if(ret)
-        ret = EVP_DecryptFinal_ex(&ciph_ctx, (unsigned char *)tmp_buf, &tmp_len);
+        ret = EVP_DecryptFinal_ex(&ciph_ctx, oblock+16, &tmp_len);
 
-    if (ret)
-        iov->data.length += 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));
+    memset(oblock,0,sizeof(oblock));
+    OPENSSL_free(iblock);
+    OPENSSL_free(oblock);
+
     if (!ret)
         return KRB5_CRYPTO_INTERNAL;
     return 0;
index ab3c6641b95fd2a8a33a8780aa9d9be6c10e6057..4445af0d8f10e3d83c4a0b0c7b7f2e8c8ae5e693 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/* lib/crypto/openssl/enc_provider/des3.c
  */
 
 #include "k5-int.h"
@@ -14,8 +14,6 @@ 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 != KRB5_MIT_DES3_KEYSIZE)
@@ -27,13 +25,6 @@ validate(const krb5_keyblock *key, const krb5_data *ivec,
     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;
 }
 
@@ -42,7 +33,6 @@ 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];
@@ -58,13 +48,6 @@ validate_iov(const krb5_keyblock *key, const krb5_data *ivec,
     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;
 }
 
@@ -72,12 +55,12 @@ 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 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)
@@ -87,11 +70,10 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
     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 * 2;
+    tmp_buf = OPENSSL_malloc(tmp_buf_len);
     if (!tmp_buf)
         return ENOMEM;
 
@@ -101,9 +83,11 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
                              (ivec && ivec->data) ? iv : NULL);
     if (ret) {
         EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
-        ret = EVP_EncryptUpdate(&ciph_ctx, tmp_buf,  &tmp_len,
+        ret = EVP_EncryptUpdate(&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_EncryptFinal_ex(&ciph_ctx, tmp_buf+tmp_len, &tmp_len);
         }
@@ -113,11 +97,12 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec,
 
     if (ret)
         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)
         return KRB5_CRYPTO_INTERNAL;
+
     return 0;
 
 }
@@ -176,61 +161,44 @@ k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec,
 
 }
 
-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;
+    int ret = 0, tmp_len = MIT_DES_BLOCK_LENGTH;
     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];
 
+    struct iov_block_state input_pos, output_pos;
+    int oblock_len = MIT_DES_BLOCK_LENGTH*num_data;
+    unsigned char  *iblock, *oblock;
+
     ret = validate_iov(key, ivec, data, num_data);
     if (ret)
-       return ret;
+        return ret;
+
+    iblock = OPENSSL_malloc(MIT_DES_BLOCK_LENGTH);
+    if (!iblock)
+        return ENOMEM;
+    oblock = OPENSSL_malloc(oblock_len);
+    if (!oblock)
+        return ENOMEM;
+
+    IOV_BLOCK_STATE_INIT(&input_pos);
+    IOV_BLOCK_STATE_INIT(&output_pos);
+
+    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);
 
@@ -239,48 +207,43 @@ k5_des3_encrypt_iov(const krb5_keyblock *key,
     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;
-        }
+    EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+
+    for (;;) {
+
+        if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH,
+                                     data, num_data, &input_pos))
+            break;
+
+        if (input_pos.iov_pos == num_data)
+            break;
+
+        ret = EVP_EncryptUpdate(&ciph_ctx, oblock, &tmp_len,
+                                (unsigned char *)iblock, input_pos.data_pos);
+        if (!ret) break;
+
+        krb5int_c_iov_put_block(data, num_data,
+                                oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
     }
+
     if(ret)
-        ret = EVP_EncryptFinal_ex(&ciph_ctx, (unsigned char *)tmp_buf, &tmp_len);
+        ret = EVP_EncryptFinal_ex(&ciph_ctx, oblock+input_pos.data_pos, &tmp_len);
 
-    if (ret)
-        iov->data.length += 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));
+    memset(oblock,0,sizeof(oblock));
+    OPENSSL_free(iblock);
+    OPENSSL_free(oblock);
+
     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
@@ -289,21 +252,84 @@ k5_des3_decrypt_iov(const krb5_keyblock *key,
                    krb5_crypto_iov *data,
                    size_t num_data)
 {
-    mit_des3_key_schedule schedule;
-    krb5_error_code err;
+    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];
+
+    struct iov_block_state input_pos, output_pos;
+    int oblock_len = MIT_DES_BLOCK_LENGTH*num_data;
+    unsigned char  *iblock, *oblock;
 
-    err = validate_and_schedule_iov(key, ivec, data, num_data, &schedule);
-    if (err)
-        return err;
+    ret = validate_iov(key, ivec, data, num_data);
+    if (ret)
+        return ret;
 
-    /* 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);
+    iblock = OPENSSL_malloc(MIT_DES_BLOCK_LENGTH);
+    if (!iblock)
+        return ENOMEM;
+    oblock = OPENSSL_malloc(oblock_len);
+    if (!oblock)
+        return ENOMEM;
 
-    zap(schedule, sizeof(schedule));
+    IOV_BLOCK_STATE_INIT(&input_pos);
+    IOV_BLOCK_STATE_INIT(&output_pos);
+
+    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);
 
-    return(0);
+    ret = EVP_DecryptInit_ex(&ciph_ctx, EVP_des_ede3_cbc(), NULL,
+                             keybuf, (ivec && ivec->data) ? iv : NULL);
+    if (!ret)
+        return KRB5_CRYPTO_INTERNAL;
+
+    EVP_CIPHER_CTX_set_padding(&ciph_ctx,0);
+
+    for (;;) {
+
+        if (!krb5int_c_iov_get_block(iblock, MIT_DES_BLOCK_LENGTH,
+                                     data, num_data, &input_pos))
+            break;
+
+        if (input_pos.iov_pos == num_data)
+            break;
+
+        ret = EVP_DecryptUpdate(&ciph_ctx, oblock, &tmp_len,
+                                (unsigned char *)iblock, input_pos.data_pos);
+        if (!ret) break;
+
+        krb5int_c_iov_put_block(data, num_data,
+                                oblock, MIT_DES_BLOCK_LENGTH, &output_pos);
+    }
+
+    if(ret)
+        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));
+    memset(oblock,0,sizeof(oblock));
+    OPENSSL_free(iblock);
+    OPENSSL_free(oblock);
+
+    if (!ret)
+        return KRB5_CRYPTO_INTERNAL;
+    return 0;
 }
 
 const struct krb5_enc_provider krb5int_enc_des3 = {
index 08bd859bd955ab11aba5a1e6e5d78fbb4a1a5ca8..455a47faaf4aa69265d2b0f4a52958cd6e1a0057 100644 (file)
@@ -1,11 +1,9 @@
-/* arcfour.c 
+/*  lib/crypto/openssl/enc_provider/rc4.c
  *
  * #include STD_DISCLAIMER
  */
 
 #include "k5-int.h"
-#include "arcfour-int.h"
-#include "enc_provider.h"
 #include <aead.h>
 #include <rand2key.h>
 #include <openssl/evp.h>
 #define RC4_BLOCK_SIZE 1 
 
 /* Interface layer to kerb5 crypto layer */
+
+/* prototypes */
 static krb5_error_code
 k5_arcfour_docrypt(const krb5_keyblock *, const krb5_data *,
            const krb5_data *, krb5_data *);
-
 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 */
+/* The workhorse of the arcfour system,
+ * this impliments the cipher
+ */
+
+/* In-place rc4 crypto */
 static krb5_error_code
 k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state,
            const krb5_data *input, krb5_data *output)
@@ -44,26 +47,30 @@ k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state,
     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);
+        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;
+
+    output->length += tmp_len;
+
     return 0;
 }
 
-
-/* In-place decryption */
+/* In-place IOV crypto */
 static krb5_error_code
 k5_arcfour_docrypt_iov(const krb5_keyblock *key,
                const krb5_data *state,
@@ -72,10 +79,10 @@ k5_arcfour_docrypt_iov(const krb5_keyblock *key,
 {
     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   *keybuf  = NULL ;
     unsigned char   *tmp_buf = NULL;
+    krb5_crypto_iov *iov     = NULL;
+    EVP_CIPHER_CTX  ciph_ctx;
 
     keybuf=key->contents;
     keybuf[key->length] = '\0';
@@ -93,7 +100,7 @@ k5_arcfour_docrypt_iov(const krb5_keyblock *key,
 
         if (ENCRYPT_IOV(iov)) {
             tmp_buf=(unsigned char *)iov->data.data;
-            ret = EVP_EncryptUpdate(&ciph_ctx, 
+            ret = EVP_EncryptUpdate(&ciph_ctx,
                       tmp_buf, &tmp_len,
                       (unsigned char *)iov->data.data, iov->data.length);
             if (!ret) break;
@@ -102,12 +109,14 @@ k5_arcfour_docrypt_iov(const krb5_keyblock *key,
     }
     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 KRB5_CRYPTO_INTERNAL;
+
+    iov->data.length += tmp_len;
+
     return 0;
 }