/*
  We're essentially using three salts, but we're going to pack it into a single blob for now.

  Input:  $NETNTLMv2$USER_DOMAIN$_SERVER_CHALLENGE_$_NTLMv2_RESP_$_CLIENT_CHALLENGE_
    Username: <=20
    Domain: <=15
    Server Challenge: 8 bytes
    Client Challenge: ???
  Output: Identity length, Identity(UTF16)\0, Challenge Size, Server Challenge + Client Challenge
*/
static void *get_salt(char *ciphertext)
{
  static unsigned char *binary_salt;
  int i, identity_length, challenge_size;
  char *pos = NULL;
#if !ARCH_ALLOWS_UNALIGNED
  static unsigned *bs2;
  if (!bs2) bs2 = mem_alloc_tiny(SALT_SIZE, MEM_ALIGN_WORD);
#endif

  if (!binary_salt) binary_salt = mem_alloc_tiny(SALT_SIZE, MEM_ALIGN_WORD);

  /* Calculate identity length */
  for (pos = ciphertext + 11; *pos != '$'; pos++);

  /* Convert identity (username + domain) string to NT unicode */
#if !ARCH_ALLOWS_UNALIGNED
  identity_length = enc_to_utf16((uint16 *)bs2, 2 * (USERNAME_LENGTH + DOMAIN_LENGTH), (uchar *)ciphertext + 11, pos - (ciphertext + 11)) * sizeof(int16);
  if (identity_length < 0) // Truncated at Unicode conversion.
	  identity_length = strlen16((UTF16 *)bs2) * sizeof(int16);
  memcpy(&binary_salt[1], bs2, identity_length);
#else
  identity_length = enc_to_utf16((uint16 *)&binary_salt[1], 2 * (USERNAME_LENGTH + DOMAIN_LENGTH), (uchar *)ciphertext + 11, pos - (ciphertext + 11)) * sizeof(int16);
  if (identity_length < 0) // Truncated at Unicode conversion.
	  identity_length = strlen16((UTF16 *)&binary_salt[1]) * sizeof(int16);
#endif

  /* Set server and client challenge size */

  /* Skip: $NETNTLMv2$USER_DOMAIN$ */
  ciphertext = pos + 1;

  /* SERVER_CHALLENGE$NTLMV2_RESPONSE$CLIENT_CHALLENGE --> SERVER_CHALLENGECLIENT_CHALLENGE */
  /* CIPHERTEXT == NTLMV2_RESPONSE (16 bytes / 32 characters) */
  challenge_size = (strlen(ciphertext) - CIPHERTEXT_LENGTH - 2) / 2;

  /* Store identity length */
  binary_salt[0] = identity_length;

  /* Set challenge size in response - 2 bytes */
  memset(binary_salt + 1 + identity_length, 0, 1);
  memset(binary_salt + 1 + identity_length + 1, (challenge_size & 0xFF00) >> 8, 1);
  memset(binary_salt + 1 + identity_length + 2, challenge_size & 0x00FF, 1);

  /* Set server challenge */
  for (i = 0; i < SERVER_CHALL_LENGTH / 2; i++)
    binary_salt[identity_length + 1 + 2 + 1 + i] = (atoi16[ARCH_INDEX(ciphertext[i*2])] << 4) + atoi16[ARCH_INDEX(ciphertext[i*2+1])];

  /* Set client challenge */
  ciphertext += SERVER_CHALL_LENGTH + 1 + CIPHERTEXT_LENGTH + 1;
  for (i = 0; i < strlen(ciphertext) / 2; ++i)
    binary_salt[identity_length + 1 + 2 + 1 + SERVER_CHALL_LENGTH / 2 + i] = (atoi16[ARCH_INDEX(ciphertext[i*2])] << 4) + atoi16[ARCH_INDEX(ciphertext[i*2+1])];

  /* Return a concatenation of the server and client challenges and the identity value */
  return (void*)binary_salt;
}
static void DCC(unsigned char *salt, unsigned int username_len,
                unsigned int *dcc_hash, unsigned int count)
{
	unsigned int id ;
	unsigned int buffer[64] ;
	unsigned int nt_hash[69] ; // large enough to handle 128 byte user name (when we expand to that size).
	int password_len;
	MD4_CTX ctx;

	for (id = 0; id < count; id++) {
		/* Proper Unicode conversion from UTF-8 or codepage */
		password_len = enc_to_utf16((UTF16*)buffer,
		                            MAX_PLAINTEXT_LENGTH,
		                            (UTF8*)key_host[id],
		                            strlen((const char*)key_host[id]));
		/* Handle truncation */
		if (password_len < 0)
			password_len = strlen16((UTF16*)buffer);

		// generate MD4 hash of the password (NT hash)
		MD4_Init(&ctx);
		MD4_Update(&ctx, buffer, password_len<<1);
		MD4_Final((unsigned char*)nt_hash, &ctx);

		// concatenate NT hash and the username (salt)
		memcpy((unsigned char *)nt_hash + 16, salt, username_len << 1) ;

		MD4_Init(&ctx);
		MD4_Update(&ctx, nt_hash, (username_len<<1)+16);
		MD4_Final((unsigned char*)(dcc_hash+4*id), &ctx);
	}
}
static int crypt_all(int *pcount, struct db_salt *salt)
{
	const int count = *pcount;
	int index = 0;
#ifdef _OPENMP
#pragma omp parallel for
#endif
	for (index = 0; index < count; index++)
	{
		unsigned char passwordBuf[PLAINTEXT_LENGTH*2+2];
		int len;
		len = enc_to_utf16((UTF16*)passwordBuf, PLAINTEXT_LENGTH,
		                   (UTF8*)saved_key[index], strlen(saved_key[index]));
		if (len < 0)
			len = strlen16((UTF16*)passwordBuf);
		len <<= 1;
		if(cur_salt->version == 0) {
			SHA_CTX ctx;
			SHA1_Init(&ctx);
			SHA1_Update(&ctx, cur_salt->esalt, 16);
			SHA1_Update(&ctx, passwordBuf, len);
			SHA1_Final((unsigned char*)crypt_out[index], &ctx);
		}
		else if(cur_salt->version == 1) {
			SHA256_CTX ctx;
			SHA256_Init(&ctx);
			SHA256_Update(&ctx, cur_salt->esalt, 16);
			SHA256_Update(&ctx, passwordBuf, len);
			SHA256_Final((unsigned char*)crypt_out[index], &ctx);
		}
	}
	return count;
}
static unsigned char* GeneratePasswordHashUsingSHA1(char *password)
{
	unsigned char hashBuf[20], *inputBuf, *key, *final;
	/* H(0) = H(salt, password)
	 * hashBuf = SHA1Hash(salt, password);
	 * create input buffer for SHA1 from salt and unicode version of password */
	unsigned char passwordBuf[512] = {0};
	int passwordBufSize;
	int i;
	SHA_CTX ctx;

	/* convert key to UTF-16LE */
	passwordBufSize = enc_to_utf16((UTF16*)passwordBuf, 125, (UTF8*)password, strlen(password));
	if (passwordBufSize < 0)
		passwordBufSize = strlen16((UTF16*)passwordBuf);
	passwordBufSize <<= 1;

	inputBuf = (unsigned char *)malloc(salt_struct->saltSize + passwordBufSize);
	memcpy(inputBuf, salt_struct->osalt, salt_struct->saltSize);
	memcpy(inputBuf + salt_struct->saltSize, passwordBuf, passwordBufSize);
	SHA1_Init(&ctx);
	SHA1_Update(&ctx, inputBuf, salt_struct->saltSize + passwordBufSize);
	SHA1_Final(hashBuf, &ctx);
	free(inputBuf);

	/* Generate each hash in turn
	 * H(n) = H(i, H(n-1))
	 * hashBuf = SHA1Hash(i, hashBuf); */
	// Create an input buffer for the hash.  This will be 4 bytes larger than
	// the hash to accommodate the unsigned int iterator value.
	inputBuf = (unsigned char *)malloc(0x14 + 0x04);
	// Create a byte array of the integer and put at the front of the input buffer
	// 1.3.6 says that little-endian byte ordering is expected
	memcpy(inputBuf + 4, hashBuf, 20);
	for (i = 0; i < 50000; i++) {
		*(int *)inputBuf = i; // XXX: size & endianness
		// 'append' the previously generated hash to the input buffer
		SHA1_Init(&ctx);
		SHA1_Update(&ctx, inputBuf, 0x14 + 0x04);
		SHA1_Final(inputBuf + 4, &ctx);
	}
	// Finally, append "block" (0) to H(n)
	// hashBuf = SHA1Hash(hashBuf, 0);
	i = 0;
	memmove(inputBuf, inputBuf + 4, 20);
	memcpy(inputBuf + 20, &i, 4); // XXX: size & endianness
	SHA1_Init(&ctx);
	SHA1_Update(&ctx, inputBuf, 0x14 + 0x04);
	SHA1_Final(hashBuf, &ctx);
	free(inputBuf);

	key = DeriveKey(hashBuf);

	// Should handle the case of longer key lengths as shown in 2.3.4.9
	// Grab the key length bytes of the final hash as the encrypytion key
	final = (unsigned char *)malloc(salt_struct->keySize/8);
static void sevenzip_set_key(char *key, int index)
{
	UTF16 c_key[PLAINTEXT_LENGTH + 1];
	int length = strlen(key);

	/* Convert password to utf-16-le format (--encoding aware) */
	length = enc_to_utf16(c_key, PLAINTEXT_LENGTH,
	                      (UTF8*)key, length);
	if (length <= 0)
		length = strlen16(c_key);
	inbuffer[index].length = length;
	memcpy(inbuffer[index].v, c_key, 2 * length);
}
static char *get_key(int index)
{
	static UTF16 u16[PLAINTEXT_LENGTH + 1];
	static UTF8 out[3 * PLAINTEXT_LENGTH + 1];
	int i, len = saved_idx[index + 1] - saved_idx[index];
	UTF8 *key = (UTF8*)&saved_key[saved_idx[index]];

	for (i = 0; i < len; i++)
		out[i] = *key++;
	out[i] = 0;

	/* Ensure we truncate just like the GPU conversion does */
	enc_to_utf16(u16, PLAINTEXT_LENGTH, (UTF8*)out, len);
	return (char*)utf16_to_enc(u16);
}
static void set_key(char *key, int index)
{
	int plen;
	UTF16 buf[PLAINTEXT_LENGTH + 1];

	/* UTF-16LE encode the password, encoding aware */
	plen = enc_to_utf16(buf, PLAINTEXT_LENGTH, (UTF8*) key, strlen(key));

	if (plen < 0)
		plen = strlen16(buf);

	memcpy(&saved_key[UNICODE_LENGTH * index], buf, UNICODE_LENGTH);

	saved_len[index] = plen << 1;

#ifdef CL_VERSION_1_0
	new_keys = 1;
#endif
}
static void set_key(char *key, int index)
{
    UTF16 *utfkey = (UTF16*)&saved_key[index * UNICODE_LENGTH];

    /* Clean slate */
    memset(utfkey, 0, UNICODE_LENGTH);

    /* convert key to UTF-16LE */
    saved_len[index] = enc_to_utf16(utfkey, PLAINTEXT_LENGTH, (UTF8*)key, strlen(key));
    if (saved_len[index] < 0)
        saved_len[index] = strlen16(utfkey);

    /* Prepare for GPU */
    utfkey[saved_len[index]] = 0x80;

    saved_len[index] <<= 1;

    new_keys = 1;
    //dump_stuff_msg("key buffer", &saved_key[index*UNICODE_LENGTH], UNICODE_LENGTH);
}
Exemple #9
0
/* We're essentially using three salts, but we're going to pack it into a single blob for now.
   |Client Challenge (8 Bytes)|Server Challenge (8 Bytes)|Unicode(Username (<=20).Domain (<=15))
*/
static void *get_salt(char *ciphertext)
{
  static unsigned char *binary_salt;
  unsigned char identity[USERNAME_LENGTH + DOMAIN_LENGTH + 1];
  UTF16 identity_ucs2[USERNAME_LENGTH + DOMAIN_LENGTH + 1];
  int i, identity_length;
  int identity_ucs2_length;
  char *pos = NULL;

  if (!binary_salt) binary_salt = mem_alloc_tiny(SALT_SIZE, MEM_ALIGN_WORD);

  memset(binary_salt, 0, SALT_SIZE);
  /* Calculate identity length */
  for (pos = ciphertext + 9; *pos != '$'; pos++);
  identity_length = pos - (ciphertext + 9);

  /* Convert identity (username + domain) string to NT unicode */
  strnzcpy((char *)identity, ciphertext + 9, sizeof(identity));
  identity_ucs2_length = enc_to_utf16((UTF16 *)identity_ucs2, USERNAME_LENGTH + DOMAIN_LENGTH, (UTF8 *)identity, identity_length) * sizeof(int16);

  if (identity_ucs2_length < 0) // Truncated at Unicode conversion.
	  identity_ucs2_length = strlen16((UTF16 *)identity_ucs2) * sizeof(int16);

  binary_salt[16] = (unsigned char)identity_ucs2_length;
  memcpy(&binary_salt[17], (char *)identity_ucs2, identity_ucs2_length);

  /* Set server challenge */
  ciphertext += 10 + identity_length;

  for (i = 0; i < 8; i++)
    binary_salt[i] = (atoi16[ARCH_INDEX(ciphertext[i*2])] << 4) + atoi16[ARCH_INDEX(ciphertext[i*2+1])];

  /* Set client challenge */
  ciphertext += 2 + CHALLENGE_LENGTH / 2 + CIPHERTEXT_LENGTH;

  for (i = 0; i < 8; ++i)
    binary_salt[i + 8] = (atoi16[ARCH_INDEX(ciphertext[i*2])] << 4) + atoi16[ARCH_INDEX(ciphertext[i*2+1])];

  /* Return a concatenation of the server and client challenges and the identity value */
  return (void*)binary_salt;
}
static int crypt_all(int *pcount, struct db_salt *salt)
{
	const int count = *pcount ;
	int salt_len;
#ifdef _DEBUG
	struct timeval startc, endc, startg, endg ;
	gettimeofday(&startc, NULL) ;
#endif
	UTF16 salt_host[MAX_SALT_LENGTH + 1];

	memset(salt_host, 0, sizeof(salt_host));

	/* Proper Unicode conversion from UTF-8 or codepage */
	salt_len = enc_to_utf16(salt_host,
	                        MAX_SALT_LENGTH,
	                        (UTF8*)currentsalt.username,
	                        currentsalt.length);
	/* Handle truncation */
	if (salt_len < 0)
		salt_len = strlen16(salt_host);

	DCC((unsigned char*)salt_host, salt_len, dcc_hash_host, count) ;

	if(salt_len > 22)
		pbkdf2_iter0(dcc_hash_host,(unsigned char*)salt_host, (salt_len << 1) , count);

#ifdef _DEBUG
	gettimeofday(&startg, NULL) ;
#endif
	///defined in common_opencl_pbkdf2.c. Details provided in common_opencl_pbkdf2.h
	pbkdf2_divide_work(dcc_hash_host, (cl_uint*)salt_host, salt_len, currentsalt.iter_cnt, dcc2_hash_host, hmac_sha1_out, count) ;

#ifdef _DEBUG
	gettimeofday(&endg, NULL);
	gettimeofday(&endc, NULL);
	fprintf(stderr, "\nGPU:%f  ",(endg.tv_sec - startg.tv_sec) + (double)(endg.tv_usec - startg.tv_usec) / 1000000.000) ;
	fprintf(stderr, "CPU:%f  ",(endc.tv_sec - startc.tv_sec) + (double)(endc.tv_usec - startc.tv_usec) / 1000000.000 - ((endg.tv_sec - startg.tv_sec) + (double)(endg.tv_usec - startg.tv_usec) / 1000000.000)) ;
#endif
	return count ;
}
Exemple #11
0
void sevenzip_kdf(UTF8 *password, unsigned char *master)
{
	int len;
	long long rounds = (long long) 1 << cur_salt->NumCyclesPower;
	long long round;
	UTF16 buffer[PLAINTEXT_LENGTH + 1];
#if !ARCH_LITTLE_ENDIAN
	int i;
	unsigned char temp[8] = { 0,0,0,0,0,0,0,0 };
#endif
	SHA256_CTX sha;

	/* Convert password to utf-16-le format (--encoding aware) */
	len = enc_to_utf16(buffer, PLAINTEXT_LENGTH, password, strlen((char*)password));
	if (len <= 0) {
		password[-len] = 0; // match truncation
		len = strlen16(buffer);
	}
	len *= 2;

	/* kdf */
        SHA256_Init(&sha);
	for (round = 0; round < rounds; round++) {
		//SHA256_Update(&sha, "", cur_salt->SaltSize);
		SHA256_Update(&sha, (char*)buffer, len);
#if ARCH_LITTLE_ENDIAN
		SHA256_Update(&sha, (char*)&round, 8);
#else
		SHA256_Update(&sha, temp, 8);
		for (i = 0; i < 8; i++)
			if (++(temp[i]) != 0)
				break;
#endif
	}
	SHA256_Final(master, &sha);
}