diff -urpN magnum-jumbo/src/osx10.8_fmt_plug.c magnum-jumbo_10.8//src/osx10.8_fmt_plug.c --- magnum-jumbo/src/osx10.8_fmt_plug.c 1970-01-01 00:00:00.000000000 +0000 +++ magnum-jumbo_10.8//src/osx10.8_fmt_plug.c 2012-09-08 16:04:26.015700362 +0000 @@ -0,0 +1,278 @@ +/* +* This software is Copyright (c) 2012 Lukas Odzioba +* and it is hereby released to the general public under the following terms: +* Redistribution and use in source and binary forms, with or without modification, are permitted. +* +* Based on hmac-sha512 by magnum +*/ + +#include +#if OPENSSL_VERSION_NUMBER >= 0x00908000 + +#include +#include +#include +#include "misc.h" +#include "arch.h" +#include "common.h" +#include "formats.h" +#include + +#define uint8_t unsigned char +#define uint16_t unsigned short +#define uint32_t unsigned int +#define uint64_t unsigned long long int + +#define FORMAT_LABEL "osx-10.8" +#define FORMAT_NAME "OSX 10.8" +#define ALGORITHM_NAME "PBKDF2-SHA512 CPU" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 +#define KEYS_PER_CRYPT 1 + +#define PAD_SIZE 128 +#define PLAINTEXT_LENGTH 15 +#define BINARY_SIZE 64 +#define SALT_SIZE sizeof(osx_salt) +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + + +/** Uncomment to see debug info **/ +//#define DEBUG + +static struct fmt_tests tests[] = { + {"$ml$23923$c3fa2e153466f7619286024fe7d812d0a8ae836295f84b9133ccc65456519fc3$ccb903ee691ade6d5dee9b3c6931ebed6ddbb1348f1b26c21add8ba0d45f27e61e97c0b80d9a18020944bb78f1ebda6fdd79c5cf08a12c80522caf987c287b6d", "openwall"}, + {"$ml$37174$ef768765ba15907760b71789fe62436e3584dfadbbf1eb8bf98673b60ff4e12b$294d42f6e0c3a93d598340bfb256efd630b53f32173c2b0d278eafab3753c10ec57b7d66e0fa79be3b80b3693e515cdd06e9e9d26d665b830159dcae152ad156", "m\xC3\xBCller"}, +{NULL} +}; + +typedef struct { + uint8_t length; + uint8_t v[15]; +} osx_pass; + +typedef struct { + uint8_t cracked;/** true if calculated hash was equal with osx_salt.hash **/ +} osx_crack; + +typedef struct { + uint8_t length; + uint8_t salt[64]; + uint32_t rounds; + uint64_t hash[16]; /** 512bits **/ +} osx_salt; + +static uint8_t any_cracked; +static osx_pass *host_pass; /** plain ciphertexts **/ +static osx_salt *host_salt; /** salt **/ +static osx_crack *host_crack; /** cracked or no **/ + +static void init(struct fmt_main *pFmt) +{ + host_pass = + mem_calloc_tiny(sizeof(osx_pass) * + pFmt->params.max_keys_per_crypt, MEM_ALIGN_NONE); + host_salt = mem_calloc_tiny(sizeof(osx_salt), MEM_ALIGN_NONE); + host_crack = + mem_calloc_tiny(sizeof(osx_crack) * + pFmt->params.max_keys_per_crypt, MEM_ALIGN_WORD); + any_cracked = 1; /** to clear cracked list in set_salt **/ +} + +static int valid(char *ciphertext, struct fmt_main *pFmt) +{ + return !strncmp(ciphertext, "$ml$", strlen("$ml$")); +} + +static void bad_ciphertext(char *ciphertext) +{ + fprintf(stderr, "get_salt(%s) Error - probably ciphertext is broken\n", + ciphertext); + exit(1); +} + +static void *get_salt(char *ciphertext) +{ + static osx_salt salt; + + char *p, *c = ciphertext; + int i, saltlen; + c += strlen("$ml$"); + salt.rounds = atoi(c); + assert(salt.rounds > 0); +#ifdef DEBUG + printf("get_salt(%s)\n", ciphertext); + printf("rounds=%d\n", salt.rounds); +#endif + c = strchr(c, '$'); + if (c++ == NULL) { + bad_ciphertext(ciphertext); + } + p = strchr(c, '$'); + if (p == NULL) { + bad_ciphertext(ciphertext); + } + saltlen = 0; + while (c < p) { /** extract salt **/ + salt.salt[saltlen++] = + atoi16[tolower(c[0])] * 16 + atoi16[tolower(c[1])]; + c += 2; + } + salt.length = saltlen; + c += 1; /** step over '$' between salt and hash **/ + p = c + strlen(c); /** end of ciphertext **/ + uint8_t *dest = (uint8_t *) salt.hash; + i = 0; + while (c < p) { + dest[i++] = atoi16[tolower(c[0])] * 16 + atoi16[tolower(c[1])]; + c += 2; + } + return (void *) &salt; +} + + +static void set_salt(void *salt) +{ + memcpy(host_salt, salt, SALT_SIZE); + any_cracked = 0; + memset(host_crack, 0, sizeof(osx_crack) * KEYS_PER_CRYPT); +} + + + +static void hmac_sha512(uint8_t * pass, uint8_t passlen, uint8_t * salt, + uint8_t saltlen, uint32_t add, uint64_t * ret) +{ + uint8_t i, ipad[PAD_SIZE], opad[PAD_SIZE]; + memset(ipad, 0x36, PAD_SIZE); + memset(opad, 0x5c, PAD_SIZE); + + for (i = 0; i < passlen; i++) { + ipad[i] ^= pass[i]; + opad[i] ^= pass[i]; + } + SHA512_CTX ctx; + + SHA512_Init(&ctx); + SHA512_Update(&ctx, ipad, PAD_SIZE); + SHA512_Update(&ctx, salt, saltlen); + if (add > 0) + SHA512_Update(&ctx, &add, 4); + SHA512_Final((uint8_t *) ret, &ctx); + + SHA512_Init(&ctx); + SHA512_Update(&ctx, opad, PAD_SIZE); + SHA512_Update(&ctx, (uint8_t *) ret, BINARY_SIZE); + SHA512_Final((uint8_t *) ret, &ctx); +} + + +static void crypt_all(int count) +{ + int index = 0; + any_cracked = 0; + + for (index = 0; index < count; index++) { + int i, j; + uint64_t tmp[BINARY_SIZE]; + uint64_t key[BINARY_SIZE]; + hmac_sha512(host_pass->v, host_pass->length, + (uint8_t *) host_salt->salt, host_salt->length, 0x01000000, + tmp); + memcpy(key, tmp, BINARY_SIZE); + + for (i = 1; i < host_salt->rounds; i++) { + hmac_sha512(host_pass->v, host_pass->length, + (uint8_t *) tmp, BINARY_SIZE, 0, tmp); + for (j = 0; j < 8; j++) + key[j] ^= tmp[j]; + } + +#ifdef DEBUG + printf("hash[%d]:", index); + for (j = 0; j < 16; j++) { + printf("%08x ", ((uint32_t *) key)[j]); + } + puts(""); +#endif + if (!memcmp(host_salt->hash, key, BINARY_SIZE)) { + host_crack[index].cracked = 1; + any_cracked = 1; + } + } +} + +static int cmp_all(void *binary, int count) +{ + return any_cracked; +} + +static int cmp_one(void *binary, int index) +{ + return host_crack[index].cracked; +} + +static int cmp_exact(char *source, int index) +{ + return host_crack[index].cracked; +} + +static void set_key(char *key, int index) +{ +#ifdef DEBUG + printf("set_key(%d)=[%s]\n", index, key); +#endif + int saved_key_length = MIN(strlen(key), PLAINTEXT_LENGTH); + memcpy(host_pass[index].v, key, saved_key_length); + host_pass[index].length = saved_key_length; +} + +static char *get_key(int index) +{ + static char ret[PLAINTEXT_LENGTH + 1]; + memcpy(ret, host_pass[index].v, PLAINTEXT_LENGTH); + ret[MIN(host_pass[index].length, PLAINTEXT_LENGTH)] = 0; + return ret; +} + +struct fmt_main fmt_osxMountainLion = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + SALT_SIZE, + KEYS_PER_CRYPT, + KEYS_PER_CRYPT, + FMT_CASE | FMT_8_BIT, + tests + }, { + init, + fmt_default_prepare, + valid, + fmt_default_split, + fmt_default_binary, + get_salt, + { + fmt_default_binary_hash + }, + fmt_default_salt_hash, + set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + fmt_default_get_hash + }, + cmp_all, + cmp_one, + cmp_exact + } +}; +#endif