guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str, GString *salt, guint iterations) { PurpleHash *hasher; PurpleCipher *cipher; guchar *result; guint i; guchar *prev, *tmp; g_return_val_if_fail(hash != NULL, NULL); g_return_val_if_fail(str != NULL && str->len > 0, NULL); g_return_val_if_fail(salt != NULL && salt->len > 0, NULL); g_return_val_if_fail(iterations > 0, NULL); prev = g_new0(guint8, hash->size); tmp = g_new0(guint8, hash->size); result = g_new0(guint8, hash->size); hasher = hash->new_cipher(); cipher = purple_hmac_cipher_new(hasher); g_object_unref(G_OBJECT(hasher)); /* Append INT(1), a four-octet encoding of the integer 1, most significant * octet first. */ g_string_append_len(salt, "\0\0\0\1", 4); /* Compute U0 */ purple_cipher_set_key(cipher, (guchar *)str->str, str->len); purple_cipher_append(cipher, (guchar *)salt->str, salt->len); purple_cipher_digest(cipher, result, hash->size); memcpy(prev, result, hash->size); /* Compute U1...Ui */ for (i = 1; i < iterations; ++i) { guint j; purple_cipher_reset(cipher); purple_cipher_set_key(cipher, (guchar *)str->str, str->len); purple_cipher_append(cipher, prev, hash->size); purple_cipher_digest(cipher, tmp, hash->size); for (j = 0; j < hash->size; ++j) result[j] ^= tmp[j]; memcpy(prev, tmp, hash->size); } g_object_unref(G_OBJECT(cipher)); g_free(tmp); g_free(prev); return result; }
static void purple_aes_cipher_init(PurpleCipher *cipher) { purple_cipher_reset(cipher); }
static void cipher_test_aes(void) { PurpleCipher *cipher; int i = 0; gboolean fail = FALSE; purple_debug_info("cipher-test", "Running AES tests\n"); cipher = purple_aes_cipher_new(); if (cipher == NULL) { purple_debug_error("cipher-test", "AES cipher not found\n"); fail = TRUE; } while (!fail && aes_tests[i].cipher) { aes_test *test = &aes_tests[i]; gsize key_size; guchar *key; guchar cipher_s[1024], decipher_s[1024]; ssize_t cipher_len, decipher_len; gchar *cipher_b16, *deciphered; purple_debug_info("cipher-test", "Test %02d:\n", i); purple_debug_info("cipher-test", "\tTesting '%s' (%" G_GSIZE_FORMAT "bit) \n", test->plaintext ? test->plaintext : "(null)", strlen(test->key) * 8 / 2); i++; purple_cipher_reset(cipher); if (test->iv) { gsize iv_size; guchar *iv = purple_base16_decode(test->iv, &iv_size); g_assert(iv != NULL); purple_cipher_set_iv(cipher, iv, iv_size); g_free(iv); } key = purple_base16_decode(test->key, &key_size); g_assert(key != NULL); purple_cipher_set_key(cipher, key, key_size); g_free(key); if (purple_cipher_get_key_size(cipher) != key_size) { purple_debug_info("cipher-test", "\tinvalid key size\n"); fail = TRUE; continue; } cipher_len = purple_cipher_encrypt(cipher, (const guchar*)(test->plaintext ? test->plaintext : ""), test->plaintext ? (strlen(test->plaintext) + 1) : 0, cipher_s, sizeof(cipher_s)); if (cipher_len < 0) { purple_debug_info("cipher-test", "\tencryption failed\n"); fail = TRUE; continue; } cipher_b16 = purple_base16_encode(cipher_s, cipher_len); purple_debug_info("cipher-test", "\tGot: %s\n", cipher_b16); purple_debug_info("cipher-test", "\tWanted: %s\n", test->cipher); if (g_strcmp0(cipher_b16, test->cipher) != 0) { purple_debug_info("cipher-test", "\tencrypted data doesn't match\n"); g_free(cipher_b16); fail = TRUE; continue; } g_free(cipher_b16); decipher_len = purple_cipher_decrypt(cipher, cipher_s, cipher_len, decipher_s, sizeof(decipher_s)); if (decipher_len < 0) { purple_debug_info("cipher-test", "\tdecryption failed\n"); fail = TRUE; continue; } deciphered = (decipher_len > 0) ? (gchar*)decipher_s : NULL; if (g_strcmp0(deciphered, test->plaintext) != 0) { purple_debug_info("cipher-test", "\tdecrypted data doesn't match\n"); fail = TRUE; continue; } purple_debug_info("cipher-test", "\tTest OK\n"); } if (cipher != NULL) g_object_unref(cipher); if (fail) purple_debug_info("cipher-test", "AES tests FAILED\n\n"); else purple_debug_info("cipher-test", "AES tests completed successfully\n\n"); }
static void cipher_test_pbkdf2(void) { PurpleCipher *cipher; PurpleHash *hash; int i = 0; gboolean fail = FALSE; purple_debug_info("cipher-test", "Running PBKDF2 tests\n"); while (!fail && pbkdf2_tests[i].answer) { pbkdf2_test *test = &pbkdf2_tests[i]; gchar digest[2 * 32 + 1 + 10]; gchar *digest_nss = NULL; gboolean ret, skip_nss = FALSE; i++; purple_debug_info("cipher-test", "Test %02d:\n", i); purple_debug_info("cipher-test", "\tTesting '%s' with salt:'%s' hash:%s iter_count:%d \n", test->passphrase, test->salt, test->hash, test->iter_count); if (!strcmp(test->hash, "sha1")) hash = purple_sha1_hash_new(); else if (!strcmp(test->hash, "sha256")) hash = purple_sha256_hash_new(); else hash = NULL; cipher = purple_pbkdf2_cipher_new(hash); g_object_set(G_OBJECT(cipher), "iter_count", GUINT_TO_POINTER(test->iter_count), NULL); g_object_set(G_OBJECT(cipher), "out_len", GUINT_TO_POINTER(test->out_len), NULL); purple_cipher_set_salt(cipher, (const guchar*)test->salt, test->salt ? strlen(test->salt): 0); purple_cipher_set_key(cipher, (const guchar*)test->passphrase, strlen(test->passphrase)); ret = purple_cipher_digest_to_str(cipher, digest, sizeof(digest)); purple_cipher_reset(cipher); if (!ret) { purple_debug_info("cipher-test", "\tfailed\n"); fail = TRUE; g_object_unref(cipher); g_object_unref(hash); continue; } if (g_strcmp0(test->hash, "sha1") != 0) skip_nss = TRUE; if (test->out_len != 16 && test->out_len != 32) skip_nss = TRUE; #ifdef HAVE_NSS if (!skip_nss) { digest_nss = cipher_pbkdf2_nss_sha1(test->passphrase, test->salt, test->iter_count, test->out_len); } #else skip_nss = TRUE; #endif purple_debug_info("cipher-test", "\tGot: %s\n", digest); if (digest_nss) purple_debug_info("cipher-test", "\tGot from NSS: %s\n", digest_nss); purple_debug_info("cipher-test", "\tWanted: %s\n", test->answer); if (g_strcmp0(digest, test->answer) == 0 && (skip_nss || g_strcmp0(digest, digest_nss) == 0)) { purple_debug_info("cipher-test", "\tTest OK\n"); } else { purple_debug_info("cipher-test", "\twrong answer\n"); fail = TRUE; } g_object_unref(cipher); g_object_unref(hash); } if (fail) purple_debug_info("cipher-test", "PBKDF2 tests FAILED\n\n"); else purple_debug_info("cipher-test", "PBKDF2 tests completed successfully\n\n"); }