From f041d38d37ed62542968050ee3cd23a0e4a61888 Mon Sep 17 00:00:00 2001
From: magnum <magnum>
Date: Mon, 12 Sep 2011 02:44:21 +0200
Subject: [PATCH 14/14] Sybase: proper Unicode converson

---
 src/SybaseASE_fmt.c |   75 ++++++++++++++++++++++++++++++++------------------
 1 files changed, 48 insertions(+), 27 deletions(-)

diff --git a/src/SybaseASE_fmt.c b/src/SybaseASE_fmt.c
index 20f2e1f..e1c5ff0 100644
--- a/src/SybaseASE_fmt.c
+++ b/src/SybaseASE_fmt.c
@@ -1,6 +1,9 @@
 /*
- * Sybase ASE hash support patch, based on hmailserver patch by James Nobis.
- * Sybase ASE hash format description : http://marcellmajor.com/sybase_sha256.html
+ * Unicode conversion enhancements by magnum, 2011. No Rights Reserved.
+ *
+ * Sybase ASE hash support for version 15.0.2 and above, based on hmailserver
+ * patch by James Nobis.
+ * Hash format description : http://marcellmajor.com/sybase_sha256.html
  * Hacked together by Dhiru Kholia in February, 2011.
  *
  * This patch Copyright (C) 2010 by James Nobis - quel
@@ -35,7 +38,8 @@
 #include "params.h"
 #include "common.h"
 #include "formats.h"
-
+#include "options.h"
+#include "unicode.h"
 
 #define FORMAT_LABEL        "sybasease"
 #define FORMAT_NAME         "sybasease"
@@ -61,10 +65,17 @@ static struct fmt_tests SybaseASE_tests[] = {
     {NULL}
 };
 
-static char saved_salt[SALT_SIZE];
-static char saved_key[MAX_KEYS_PER_CRYPT][PLAINTEXT_LENGTH + 1];
+static char *saved_salt;
+static UTF16 prep_key[MAX_KEYS_PER_CRYPT][518 / sizeof(UTF16)];
 static ARCH_WORD_32 crypt_out[MAX_KEYS_PER_CRYPT][8];
 
+extern struct fmt_main fmt_SybaseASE;
+static void init(struct fmt_main *pFmt)
+{
+    if (options.utf8)
+        fmt_SybaseASE.params.plaintext_length = 125;
+}
+
 // TODO: strengthen checks
 static int valid(char *ciphertext, struct fmt_main *pFmt)
 {
@@ -155,21 +166,38 @@ static int get_hash_4(int index)
 
 static void set_salt(void *salt)
 {
-    memcpy(saved_salt, salt, SALT_SIZE);
+    saved_salt = salt;
 }
 
 static void set_key(char *key, int index)
 {
-    int saved_key_length = strlen(key);
-    if(saved_key_length > PLAINTEXT_LENGTH)
-        saved_key_length = PLAINTEXT_LENGTH;
-    memcpy(saved_key[index], key, saved_key_length);
-    saved_key[index][saved_key_length] = 0;
+    UTF16 *c;
+
+    /* Clean slate */
+    memset(prep_key[index], 0, 2 * PLAINTEXT_LENGTH);
+
+    /* convert key to UTF-16 - encoding aware */
+    enc_to_utf16(prep_key[index], PLAINTEXT_LENGTH, (UTF8*)key,
+                 strlen(key));
+
+    // Byte-swap to UTF-16BE
+    // This should be made optional in enc_to_utf16, for speed
+    c = prep_key[index];
+    while ((*c = *c >> 8 | *c << 8))
+        c++;
 }
 
 static char *get_key(int index)
 {
-    return saved_key[index];
+    UTF16 key_le[PLAINTEXT_LENGTH + 1];
+    UTF16 *s = prep_key[index];
+    UTF16 *d = key_le;
+
+    // Byte-swap back to UTF-16LE
+    while ((*d++ = *s >> 8 | *s << 8))
+        s++;
+
+    return (char*)utf16_to_enc(key_le);
 }
 
 static void crypt_all(int count)
@@ -177,23 +205,16 @@ static void crypt_all(int count)
     int index;
 
 #ifdef _OPENMP
-#pragma omp parallel for default(none) private(index) shared(count, crypt_out, saved_key, saved_salt)
+#pragma omp parallel for default(none) private(index) shared(count, crypt_out, prep_key, saved_salt)
 #endif
     for(index = 0; index < count; index++) {
-        unsigned char input[518] = {0};
-        int i;
-        unsigned char c;
-        int position = 1;
         SHA256_CTX ctx;
-        /* convert key to UTF-16 */
-        for(i = 0; (c = saved_key[index][i]); i++) {
-            input[position] = c;
-            position += 2;
-        }
+
         /* append salt at offset 510 */
-        memcpy(input + 510, saved_salt, 8);
+        memcpy((unsigned char *)prep_key[index] + 510, saved_salt, 8);
+
         SHA256_Init(&ctx);
-        SHA256_Update(&ctx, input, 518);
+        SHA256_Update(&ctx, prep_key[index], 518);
         SHA256_Final((unsigned char *)crypt_out[index], &ctx);
     }
 }
@@ -225,11 +246,11 @@ struct fmt_main fmt_SybaseASE = {
         SALT_SIZE,
         MIN_KEYS_PER_CRYPT,
         MAX_KEYS_PER_CRYPT,
-        FMT_CASE | FMT_8_BIT | FMT_OMP,
+        FMT_CASE | FMT_8_BIT | FMT_OMP | FMT_UNICODE | FMT_UTF8,
         SybaseASE_tests
     }, {
-        fmt_default_init,
-	fmt_default_prepare,
+        init,
+        fmt_default_prepare,
         valid,
         fmt_default_split,
         get_binary,
-- 
1.7.4.1

