1
0
mirror of https://github.com/hashcat/hashcat.git synced 2024-11-15 20:39:17 +00:00
hashcat/OpenCL/m22100-pure.cl
2019-12-31 18:42:13 +01:00

404 lines
8.8 KiB
Common Lisp

/**
* Author......: See docs/credits.txt
* License.....: MIT
*/
#define NEW_SIMD_CODE
#ifdef KERNEL_STATIC
#include "inc_vendor.h"
#include "inc_types.h"
#include "inc_platform.cl"
#include "inc_common.cl"
#include "inc_simd.cl"
#include "inc_hash_sha256.cl"
#include "inc_cipher_aes.cl"
#endif
typedef struct bitlocker
{
u32 type;
u32 iv[4];
u32 data[15];
} bitlocker_t;
typedef struct bitlocker_tmp
{
u32 last_hash[8];
u32 init_hash[8];
u32 salt[4];
} bitlocker_tmp_t;
KERNEL_FQ void m22100_init (KERN_ATTR_TMPS_ESALT (bitlocker_tmp_t, bitlocker_t))
{
/**
* base
*/
const u64 gid = get_global_id (0);
if (gid >= gid_max) return;
// sha256 of utf16le converted password:
sha256_ctx_t ctx0;
sha256_init (&ctx0);
sha256_update_global_utf16le_swap (&ctx0, pws[gid].i, pws[gid].pw_len);
sha256_final (&ctx0);
u32 w[16] = { 0 }; // 64 bytes blocks/aligned, we need 32 bytes
w[0] = ctx0.h[0];
w[1] = ctx0.h[1];
w[2] = ctx0.h[2];
w[3] = ctx0.h[3];
w[4] = ctx0.h[4];
w[5] = ctx0.h[5];
w[6] = ctx0.h[6];
w[7] = ctx0.h[7];
// sha256 of sha256:
sha256_ctx_t ctx1;
sha256_init (&ctx1);
sha256_update (&ctx1, w, 32);
sha256_final (&ctx1);
// set tmps:
tmps[gid].init_hash[0] = ctx1.h[0];
tmps[gid].init_hash[1] = ctx1.h[1];
tmps[gid].init_hash[2] = ctx1.h[2];
tmps[gid].init_hash[3] = ctx1.h[3];
tmps[gid].init_hash[4] = ctx1.h[4];
tmps[gid].init_hash[5] = ctx1.h[5];
tmps[gid].init_hash[6] = ctx1.h[6];
tmps[gid].init_hash[7] = ctx1.h[7];
tmps[gid].last_hash[0] = 0;
tmps[gid].last_hash[1] = 0;
tmps[gid].last_hash[2] = 0;
tmps[gid].last_hash[3] = 0;
tmps[gid].last_hash[4] = 0;
tmps[gid].last_hash[5] = 0;
tmps[gid].last_hash[6] = 0;
tmps[gid].last_hash[7] = 0;
tmps[gid].salt[0] = salt_bufs[salt_pos].salt_buf[0];
tmps[gid].salt[1] = salt_bufs[salt_pos].salt_buf[1];
tmps[gid].salt[2] = salt_bufs[salt_pos].salt_buf[2];
tmps[gid].salt[3] = salt_bufs[salt_pos].salt_buf[3];
}
KERNEL_FQ void m22100_loop (KERN_ATTR_TMPS_ESALT (bitlocker_tmp_t, bitlocker_t))
{
const u64 gid = get_global_id (0);
if ((gid * VECT_SIZE) >= gid_max) return;
// init
u32x w[32] = { 0 }; // 64 bytes blocks/aligned, 88 bytes needed (22 u32 = 22 * 4)
w[ 0] = packv (tmps, last_hash, gid, 0);
w[ 1] = packv (tmps, last_hash, gid, 1);
w[ 2] = packv (tmps, last_hash, gid, 2);
w[ 3] = packv (tmps, last_hash, gid, 3);
w[ 4] = packv (tmps, last_hash, gid, 4);
w[ 5] = packv (tmps, last_hash, gid, 5);
w[ 6] = packv (tmps, last_hash, gid, 6);
w[ 7] = packv (tmps, last_hash, gid, 7);
w[ 8] = packv (tmps, init_hash, gid, 0);
w[ 9] = packv (tmps, init_hash, gid, 1);
w[10] = packv (tmps, init_hash, gid, 2);
w[11] = packv (tmps, init_hash, gid, 3);
w[12] = packv (tmps, init_hash, gid, 4);
w[13] = packv (tmps, init_hash, gid, 5);
w[14] = packv (tmps, init_hash, gid, 6);
w[15] = packv (tmps, init_hash, gid, 7);
w[16] = packv (tmps, salt, gid, 0);
w[17] = packv (tmps, salt, gid, 1);
w[18] = packv (tmps, salt, gid, 2);
w[19] = packv (tmps, salt, gid, 3);
// main loop
for (u32 i = 0, j = loop_pos; i < loop_cnt; i++, j++)
{
w[20] = hc_swap32 (j);
sha256_ctx_vector_t ctx;
sha256_init_vector (&ctx);
sha256_update_vector (&ctx, w, 88);
sha256_final_vector (&ctx);
w[0] = ctx.h[0];
w[1] = ctx.h[1];
w[2] = ctx.h[2];
w[3] = ctx.h[3];
w[4] = ctx.h[4];
w[5] = ctx.h[5];
w[6] = ctx.h[6];
w[7] = ctx.h[7];
}
unpackv (tmps, last_hash, gid, 0, w[0]);
unpackv (tmps, last_hash, gid, 1, w[1]);
unpackv (tmps, last_hash, gid, 2, w[2]);
unpackv (tmps, last_hash, gid, 3, w[3]);
unpackv (tmps, last_hash, gid, 4, w[4]);
unpackv (tmps, last_hash, gid, 5, w[5]);
unpackv (tmps, last_hash, gid, 6, w[6]);
unpackv (tmps, last_hash, gid, 7, w[7]);
}
KERNEL_FQ void m22100_comp (KERN_ATTR_TMPS_ESALT (bitlocker_tmp_t, bitlocker_t))
{
const u64 gid = get_global_id (0);
const u64 lid = get_local_id (0);
const u64 lsz = get_local_size (0);
/**
* aes shared
*/
#ifdef REAL_SHM
LOCAL_VK u32 s_td0[256];
LOCAL_VK u32 s_td1[256];
LOCAL_VK u32 s_td2[256];
LOCAL_VK u32 s_td3[256];
LOCAL_VK u32 s_td4[256];
LOCAL_VK u32 s_te0[256];
LOCAL_VK u32 s_te1[256];
LOCAL_VK u32 s_te2[256];
LOCAL_VK u32 s_te3[256];
LOCAL_VK u32 s_te4[256];
for (u32 i = lid; i < 256; i += lsz)
{
s_td0[i] = td0[i];
s_td1[i] = td1[i];
s_td2[i] = td2[i];
s_td3[i] = td3[i];
s_td4[i] = td4[i];
s_te0[i] = te0[i];
s_te1[i] = te1[i];
s_te2[i] = te2[i];
s_te3[i] = te3[i];
s_te4[i] = te4[i];
}
SYNC_THREADS ();
#else
CONSTANT_AS u32a *s_td0 = td0;
CONSTANT_AS u32a *s_td1 = td1;
CONSTANT_AS u32a *s_td2 = td2;
CONSTANT_AS u32a *s_td3 = td3;
CONSTANT_AS u32a *s_td4 = td4;
CONSTANT_AS u32a *s_te0 = te0;
CONSTANT_AS u32a *s_te1 = te1;
CONSTANT_AS u32a *s_te2 = te2;
CONSTANT_AS u32a *s_te3 = te3;
CONSTANT_AS u32a *s_te4 = te4;
#endif
if (gid >= gid_max) return;
/*
* AES decrypt the data_buf
*/
// init AES
u32 ukey[8];
ukey[0] = tmps[gid].last_hash[0];
ukey[1] = tmps[gid].last_hash[1];
ukey[2] = tmps[gid].last_hash[2];
ukey[3] = tmps[gid].last_hash[3];
ukey[4] = tmps[gid].last_hash[4];
ukey[5] = tmps[gid].last_hash[5];
ukey[6] = tmps[gid].last_hash[6];
ukey[7] = tmps[gid].last_hash[7];
#define KEYLEN 60
u32 ks[KEYLEN];
AES256_set_encrypt_key (ks, ukey, s_te0, s_te1, s_te2, s_te3);
// decrypt:
u32 iv[4];
iv[0] = esalt_bufs[digests_offset].iv[0];
iv[1] = esalt_bufs[digests_offset].iv[1];
iv[2] = esalt_bufs[digests_offset].iv[2];
iv[3] = esalt_bufs[digests_offset].iv[3];
// in total we've 60 bytes: we need out0 (16 bytes) to out3 (16 bytes) for MAC verification
// 1
u32 out1[4];
AES256_encrypt (ks, iv, out1, s_te0, s_te1, s_te2, s_te3, s_te4);
// some early reject:
out1[0] ^= esalt_bufs[digests_offset].data[4]; // skip MAC for now (first 16 bytes)
if ((out1[0] & 0xffff0000) != 0x2c000000) return; // data_size must be 0x2c00
out1[1] ^= esalt_bufs[digests_offset].data[5];
if ((out1[1] & 0xffff0000) != 0x01000000) return; // version must be 0x0100
out1[2] ^= esalt_bufs[digests_offset].data[6];
if ((out1[2] & 0x00ff0000) != 0x00200000) return; // v2 must be 0x20
if ((out1[2] >> 24) > 0x05) return; // v1 must be <= 5
// if no MAC verification should be performed, we are already done:
u32 type = esalt_bufs[digests_offset].type;
if (type == 0)
{
if (atomic_inc (&hashes_shown[digests_offset]) == 0)
{
mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, 0, digests_offset + 0, gid, 0, 0, 0);
}
return;
}
out1[3] ^= esalt_bufs[digests_offset].data[7];
/*
* Decrypt the whole data buffer for MAC verification (type == 1):
*/
// 0
iv[3] = iv[3] & 0xff000000; // xx000000
u32 out0[4];
AES256_encrypt (ks, iv, out0, s_te0, s_te1, s_te2, s_te3, s_te4);
out0[0] ^= esalt_bufs[digests_offset].data[0];
out0[1] ^= esalt_bufs[digests_offset].data[1];
out0[2] ^= esalt_bufs[digests_offset].data[2];
out0[3] ^= esalt_bufs[digests_offset].data[3];
// 2
// add 2 because we already did block 1 for the early reject
iv[3] += 2; // xx000002
u32 out2[4];
AES256_encrypt (ks, iv, out2, s_te0, s_te1, s_te2, s_te3, s_te4);
out2[0] ^= esalt_bufs[digests_offset].data[ 8];
out2[1] ^= esalt_bufs[digests_offset].data[ 9];
out2[2] ^= esalt_bufs[digests_offset].data[10];
out2[3] ^= esalt_bufs[digests_offset].data[11];
// 3
iv[3] += 1; // xx000003
u32 out3[4]; // actually only 3 needed
AES256_encrypt (ks, iv, out3, s_te0, s_te1, s_te2, s_te3, s_te4);
out3[0] ^= esalt_bufs[digests_offset].data[12];
out3[1] ^= esalt_bufs[digests_offset].data[13];
out3[2] ^= esalt_bufs[digests_offset].data[14];
// compute MAC:
// out1
iv[0] = (iv[0] & 0x00ffffff) | 0x3a000000;
iv[3] = (iv[3] & 0xff000000) | 0x0000002c;
u32 mac[4];
AES256_encrypt (ks, iv, mac, s_te0, s_te1, s_te2, s_te3, s_te4);
iv[0] = mac[0] ^ out1[0];
iv[1] = mac[1] ^ out1[1];
iv[2] = mac[2] ^ out1[2];
iv[3] = mac[3] ^ out1[3];
// out2
AES256_encrypt (ks, iv, mac, s_te0, s_te1, s_te2, s_te3, s_te4);
iv[0] = mac[0] ^ out2[0];
iv[1] = mac[1] ^ out2[1];
iv[2] = mac[2] ^ out2[2];
iv[3] = mac[3] ^ out2[3];
// out3
AES256_encrypt (ks, iv, mac, s_te0, s_te1, s_te2, s_te3, s_te4);
iv[0] = mac[0] ^ out3[0];
iv[1] = mac[1] ^ out3[1];
iv[2] = mac[2] ^ out3[2];
iv[3] = mac[3];
// final
AES256_encrypt (ks, iv, mac, s_te0, s_te1, s_te2, s_te3, s_te4);
if (mac[0] != out0[0]) return;
if (mac[1] != out0[1]) return;
if (mac[2] != out0[2]) return;
if (mac[3] != out0[3]) return;
// if we end up here, we are sure to have found the correct password:
if (atomic_inc (&hashes_shown[digests_offset]) == 0)
{
mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, 0, digests_offset + 0, gid, 0, 0, 0);
}
}