Beispiel #1
0
void hmac_sha256
(
	char *k,    /* secret key */
	int lk,    /* length of the key in bytes */
	char *d,    /* data */
	int ld    /* length of data in bytes */
)
{
	hmac_sha256_ctx hmac;
	char key[SHA256_DIGESTSIZE];
    /* If the key is longer than the hash algorithm block size,
	   let key = sha256(key), as per HMAC specifications. */
	if (lk > SHA256_BLOCKSIZE)
	{
		sha256_ctx tctx;

		sha256_begin (&tctx);
		sha256_hash ((unsigned char *) k, lk, &tctx);
		sha256_end ((unsigned char *) key, &tctx);

		k = key;
		lk = SHA256_DIGESTSIZE;

		burn (&tctx, sizeof(tctx));		// Prevent leaks
	}
	hmac_sha256_internal(k, lk, d, ld, &hmac);
	/* Prevent leaks */
	burn(&hmac, sizeof(hmac));
	burn(key, sizeof(key));
}
Beispiel #2
0
static void hmacSha256Final(hmacSha256Context *ctx, uint8_t *mac)
{
    uint8_t tmpDigest[SHA256_DIGEST_SIZE];

    /* finalize work hash context */
    sha256_end(tmpDigest, &ctx->ctx);

    /* copy prepared outer hash to work hash */
    memcpy(&ctx->ctx, &ctx->outerCtx, sizeof(sha256_ctx));

    /* hash inner digest to work (outer) hash context */
    sha256_hash(tmpDigest, SHA256_DIGEST_SIZE, &ctx->ctx);

    /* finalize work hash context to get the hmac*/
    sha256_end(mac, &ctx->ctx);
}
Beispiel #3
0
static void calculateSHA(char *message, unsigned char *hval){
	sha256_ctx		sha_ctx[1];

	sha256_begin(sha_ctx);
	sha256_hash(message, strlen(decrypted), sha_ctx);
	sha256_end(hval, sha_ctx);
}
Beispiel #4
0
void hmac_sha256_internal
(
	  char *k,		/* secret key. It's ensured to be always <= 32 bytes */
	  int lk,		/* length of the key in bytes */
	  char *d,		/* input data. d pointer is guaranteed to be at least 32-bytes long */
	  int ld,		/* length of input data in bytes */
	  hmac_sha256_ctx* hmac /* HMAC-SHA256 context which holds temporary variables */
)
{
	int i;
	sha256_ctx* ctx = &(hmac->ctx);
	char* buf = hmac->buf;

	/**** Inner Digest ****/

	sha256_begin (ctx);

	/* Pad the key for inner digest */
	for (i = 0; i < lk; ++i)
		buf[i] = (char) (k[i] ^ 0x36);
	for (i = lk; i < SHA256_BLOCKSIZE; ++i)
		buf[i] = 0x36;

	sha256_hash ((unsigned char *) buf, SHA256_BLOCKSIZE, ctx);
	sha256_hash ((unsigned char *) d, ld, ctx);

	sha256_end ((unsigned char *) d, ctx); /* d = inner digest */

	/**** Outer Digest ****/

	sha256_begin (ctx);

	for (i = 0; i < lk; ++i)
		buf[i] = (char) (k[i] ^ 0x5C);
	for (i = lk; i < SHA256_BLOCKSIZE; ++i)
		buf[i] = 0x5C;

	sha256_hash ((unsigned char *) buf, SHA256_BLOCKSIZE, ctx);
	sha256_hash ((unsigned char *) d, SHA256_DIGESTSIZE, ctx);

	sha256_end ((unsigned char *) d, ctx); /* d = outer digest */
}
Beispiel #5
0
void derive_key_sha256 (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, char *dk, int dklen)
{	
	hmac_sha256_ctx hmac;
	int b, l, r;
#ifndef TC_WINDOWS_BOOT
	char key[SHA256_DIGESTSIZE];
    /* If the password is longer than the hash algorithm block size,
	   let pwd = sha256(pwd), as per HMAC specifications. */
	if (pwd_len > SHA256_BLOCKSIZE)
	{
		sha256_ctx tctx;

		sha256_begin (&tctx);
		sha256_hash ((unsigned char *) pwd, pwd_len, &tctx);
		sha256_end ((unsigned char *) key, &tctx);

		pwd = key;
		pwd_len = SHA256_DIGESTSIZE;

		burn (&tctx, sizeof(tctx));		// Prevent leaks
	}
#endif

	if (dklen % SHA256_DIGESTSIZE)
	{
		l = 1 + dklen / SHA256_DIGESTSIZE;
	}
	else
	{
		l = dklen / SHA256_DIGESTSIZE;
	}

	r = dklen - (l - 1) * SHA256_DIGESTSIZE;

	/* first l - 1 blocks */
	for (b = 1; b < l; b++)
	{
		derive_u_sha256 (pwd, pwd_len, salt, salt_len, iterations, b, &hmac);
		memcpy (dk, hmac.u, SHA256_DIGESTSIZE);
		dk += SHA256_DIGESTSIZE;
	}

	/* last block */
	derive_u_sha256 (pwd, pwd_len, salt, salt_len, iterations, b, &hmac);
	memcpy (dk, hmac.u, r);


	/* Prevent possible leaks. */
	burn (&hmac, sizeof(hmac));
#ifndef TC_WINDOWS_BOOT
	burn (key, sizeof(key));
#endif
}
Beispiel #6
0
//----------------------------------------------------------------
void FileToSHA256(HANDLE Hfic, char *csha256)
{
  if (SHA1_enable)
  {
    FileToSHA1(Hfic, csha256);
    return;
  }

  //ouverture du fichier en lecture partagé
  csha256[0]=0;
  DWORD taille_fic = GetFileSize(Hfic,NULL);
  if (taille_fic>0 && taille_fic!=INVALID_FILE_SIZE)
  {
    unsigned char *buffer = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, sizeof(unsigned char*)*taille_fic+1);
    if (buffer == NULL)return;

    //lecture du fichier
    DWORD copiee, position = 0, increm = 0;
    if (taille_fic > DIXM)increm = DIXM;
    else increm = taille_fic;

    BOOL read = TRUE;
    while (position<taille_fic && increm!=0 && read)//gestion pour éviter les bug de sync permet une ouverture de fichiers énormes ^^
    {
      copiee = 0;
      read = ReadFile(Hfic, buffer+position, increm,&copiee,0);
      position +=copiee;
      if (taille_fic-position < increm)increm = taille_fic-position ;
    }

    //traitement en SHA256
    sha256_ctx    m_sha256;
    unsigned char digest[32];

    sha256_begin(&m_sha256);
    sha256_hash(buffer, taille_fic, &m_sha256);
    sha256_end(digest, &m_sha256);

    //génération du SHA256 en chaine
    unsigned short i;
    for(i=0;i<32;i++)snprintf(csha256+i*2,3,"%02x",digest[i]&0xFF);
    csha256[64]=0;
    HeapFree(GetProcessHeap(), 0,buffer);
  }
}
Beispiel #7
0
// Encrypt the master key a few times to make brute-force key-search harder
BOOL CEncryption::_TransformMasterKey(BYTE *pKeySeed)
{
	Rijndael rijndael;
	RD_UINT8 aKey[32];
	RD_UINT8 aTest[16];
	RD_UINT8 aRef[16] = { // The Rijndael class will be tested, that's the expected ciphertext
		0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
		0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89
	};
	DWORD i;
	sha256_ctx sha2;

	ASSERT(pKeySeed != NULL); if(pKeySeed == NULL) return FALSE;

	if(rijndael.init(Rijndael::ECB, Rijndael::Encrypt, (const RD_UINT8 *)pKeySeed,
		Rijndael::Key32Bytes, 0) != RIJNDAEL_SUCCESS)
	{
		return FALSE;
	}

	memcpy(m_pTransformedMasterKey, m_pMasterKey, 32);

	for(i = 0; i < m_dwKeyEncRounds; i++)
	{
		rijndael.blockEncrypt((const RD_UINT8 *)m_pTransformedMasterKey, 256, (RD_UINT8 *)m_pTransformedMasterKey);
	}

	// Do a quick test if the Rijndael class worked correctly
	for(i = 0; i < 32; i++) aKey[i] = (RD_UINT8)i;
	for(i = 0; i < 16; i++) aTest[i] = ((RD_UINT8)i << 4) | (RD_UINT8)i;
	if(rijndael.init(Rijndael::ECB, Rijndael::Encrypt, aKey, Rijndael::Key32Bytes, NULL) != RIJNDAEL_SUCCESS)
		{ ASSERT(FALSE); return FALSE; }
	if(rijndael.blockEncrypt(aTest, 128, aTest) != 128) { ASSERT(FALSE); }
	if(memcmp(aTest, aRef, 16) != 0) { ASSERT(FALSE); return FALSE; }

	// Hash once with SHA-256
	sha256_begin(&sha2);
	sha256_hash(m_pTransformedMasterKey, 32, &sha2);
	sha256_end(m_pTransformedMasterKey, &sha2);

	return TRUE;
}
Beispiel #8
0
char *TadsServerManager::gen_rand_id(void *obj)
{
    /* set up a hashing buffer */
    sha256_ctx s;
    sha256_begin(&s);

    /* add the current date/time to the hash */
    os_time_t timer = os_time(0);
    struct tm *tblock = os_localtime(&timer);
    sha256_hash((unsigned char *)tblock, sizeof(*tblock), &s);

    /* add the system timer to the hash */
    long systime = os_get_sys_clock_ms();
    sha256_hash((unsigned char *)&systime, sizeof(systime), &s);

    /* add the object address to the hash */
    sha256_hash((unsigned char *)obj, sizeof(obj), &s);

    /* add the current stack location to the hash */
    sha256_hash((unsigned char *)&obj, sizeof(void *), &s);

    /* add some random bytes from the operating system */
    unsigned char rbuf[128];
    os_gen_rand_bytes(rbuf, sizeof(rbuf));
    sha256_hash(rbuf, sizeof(rbuf), &s);

    /* compute the hash */
    unsigned char hval[32];
    sha256_end(hval, &s);

    /* convert it to hex, but just keep the low nybbles, for 32 digits */
    char *ret = lib_alloc_str(32);
    int i;
    for (i = 0 ; i < 32 ; ++i)
        ret[i] = nybble2hex(hval[i]);

    /* null-terminate the string */
    ret[i] = '\0';

    /* return the allocated string */
    return ret;
}
Beispiel #9
0
static int32_t hmacSha256Init(hmacSha256Context *ctx, const uint8_t *key, uint32_t kLength)
{
    int32_t i;
    uint8_t localPad[SHA256_BLOCK_SIZE] = {0};
    uint8_t localKey[SHA256_BLOCK_SIZE] = {0};

    if (key == NULL)
        return 0;

    memset(ctx, 0, sizeof(hmacSha256Context));

    /* check key length and reduce it if necessary */
    if (kLength > SHA256_BLOCK_SIZE) {
        sha256_begin(&ctx->ctx);
        sha256_hash(key, kLength, &ctx->ctx);
        sha256_end(localKey, &ctx->ctx);
    }
    else {
        memcpy(localKey, key, kLength);
    }
    /* prepare inner hash and hold the context */
    for (i = 0; i < SHA256_BLOCK_SIZE; i++)
        localPad[i] = localKey[i] ^ 0x36;

    sha256_begin(&ctx->innerCtx);
    sha256_hash(localPad, SHA256_BLOCK_SIZE, &ctx->innerCtx);

    /* prepare outer hash and hold the context */
    for (i = 0; i < SHA256_BLOCK_SIZE; i++)
        localPad[i] = localKey[i] ^ 0x5c;

    sha256_begin(&ctx->outerCtx);
    sha256_hash(localPad, SHA256_BLOCK_SIZE, &ctx->outerCtx);

    /* copy prepared inner hash to work hash - ready to process data */
    memcpy(&ctx->ctx, &ctx->innerCtx, sizeof(sha256_ctx));

    memset(localKey, 0, sizeof(localKey));

    return 1;
}
Beispiel #10
0
/// @brief 
bool 
FileInfoCache::file_util_get_hash(
	_In_ const wchar_t* file_path, 
	_Out_ std::string& md5, 
	_Out_ std::string& sha2)
{
	handle_ptr file_handle(
		CreateFileW(file_path,
					GENERIC_READ,
					FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
					NULL,
					OPEN_EXISTING,
					FILE_ATTRIBUTE_NORMAL,
					NULL),
		[](HANDLE h) 
		{
			if (INVALID_HANDLE_VALUE != h)
			{
				CloseHandle(h);
			}
		});

    if (INVALID_HANDLE_VALUE == file_handle.get())
    {
        log_err
            "CreateFileW() failed. path=%ws, gle = %u",
            file_path, 
			GetLastError()
            log_end;
        return false; 
    }
    
    if (INVALID_SET_FILE_POINTER == SetFilePointer(file_handle.get(), 
												   0, 
												   NULL, 
												   FILE_BEGIN))
    {
        log_err
            "SetFilePointer() failed. path=%ws, gle = %u", 
			file_path, 
			GetLastError()
            log_end;
        return false;
    }

    uint8_t sha2_buf[32];
    MD5_CTX ctx_md5;
    sha256_ctx ctx_sha2;
    MD5Init(&ctx_md5, 0);
    sha256_begin(&ctx_sha2);

    const uint32_t read_buffer_size = 4096;
    uint8_t read_buffer[read_buffer_size];
    DWORD read = read_buffer_size;

    while (read_buffer_size == read)
    {
		if (FALSE == ::ReadFile(file_handle.get(),
								read_buffer,
								read_buffer_size,
								&read,
								NULL))
        {
            log_err
                "ReadFile() failed. path=%ws, gle = %u",
                file_path,
                GetLastError()
                log_end;
            return false;
        }

        if (0 != read)
        {
            MD5Update(&ctx_md5, read_buffer, read);
            sha256_hash(read_buffer, read, &ctx_sha2);
        }
    }

    MD5Final(&ctx_md5);
    sha256_end(sha2_buf, &ctx_sha2);

	//
	//	Hash 바이너리 버퍼를 hex 문자열로 변환
	//
	if (true != bin_to_hexa_fast(sizeof(ctx_md5.digest),
								 ctx_md5.digest,
								 false,
								 md5))
	{
		log_err "bin_to_hexa_fast() failed. " log_end;
		return false;
	}

	if (true != bin_to_hexa_fast(sizeof(sha2_buf), 
								 sha2_buf, 
								 false, 
								 sha2))
	{
		log_err "bin_to_hexa_fast() failed. " log_end;
		return false;
	}
    return true;
}
Beispiel #11
0
/* The random pool mixing function */
BOOL Randmix ()
{
	if (bRandmixEnabled)
	{
		unsigned char hashOutputBuffer [MAX_DIGESTSIZE];
		WHIRLPOOL_CTX	wctx;
		RMD160_CTX		rctx;
		sha512_ctx		sctx;
		sha256_ctx		s256ctx;
		int poolIndex, digestIndex, digestSize;

		switch (HashFunction)
		{
		case RIPEMD160:
			digestSize = RIPEMD160_DIGESTSIZE;
			break;

		case SHA512:
			digestSize = SHA512_DIGESTSIZE;
			break;

		case SHA256:
			digestSize = SHA256_DIGESTSIZE;
			break;

		case WHIRLPOOL:
			digestSize = WHIRLPOOL_DIGESTSIZE;
			break;

		default:
			TC_THROW_FATAL_EXCEPTION;
		}

		if (RNG_POOL_SIZE % digestSize)
			TC_THROW_FATAL_EXCEPTION;

		for (poolIndex = 0; poolIndex < RNG_POOL_SIZE; poolIndex += digestSize)		
		{
			/* Compute the message digest of the entire pool using the selected hash function. */
			switch (HashFunction)
			{
			case RIPEMD160:
				RMD160Init(&rctx);
				RMD160Update(&rctx, pRandPool, RNG_POOL_SIZE);
				RMD160Final(hashOutputBuffer, &rctx);
				break;

			case SHA512:
				sha512_begin (&sctx);
				sha512_hash (pRandPool, RNG_POOL_SIZE, &sctx);
				sha512_end (hashOutputBuffer, &sctx);
				break;

			case SHA256:
				sha256_begin (&s256ctx);
				sha256_hash (pRandPool, RNG_POOL_SIZE, &s256ctx);
				sha256_end (hashOutputBuffer, &s256ctx);
				break;

			case WHIRLPOOL:
				WHIRLPOOL_init (&wctx);
				WHIRLPOOL_add (pRandPool, RNG_POOL_SIZE * 8, &wctx);
				WHIRLPOOL_finalize (&wctx, hashOutputBuffer);
				break;

			default:		
				// Unknown/wrong ID
				TC_THROW_FATAL_EXCEPTION;
			}

			/* XOR the resultant message digest to the pool at the poolIndex position. */
			for (digestIndex = 0; digestIndex < digestSize; digestIndex++)
			{
				pRandPool [poolIndex + digestIndex] ^= hashOutputBuffer [digestIndex];
			}
		}

		/* Prevent leaks */
		burn (hashOutputBuffer, MAX_DIGESTSIZE);	
		switch (HashFunction)
		{
		case RIPEMD160:
			burn (&rctx, sizeof(rctx));		
			break;

		case SHA512:
			burn (&sctx, sizeof(sctx));		
			break;

		case SHA256:
			burn (&s256ctx, sizeof(s256ctx));		
			break;

		case WHIRLPOOL:
			burn (&wctx, sizeof(wctx));		
			break;

		default:		
			// Unknown/wrong ID
			TC_THROW_FATAL_EXCEPTION;
		}
	}
	return TRUE;
}
Beispiel #12
0
bool CEncryption::Encrypt(const unsigned char* pInput, int nLenInput, const char* szPassword, 
						 unsigned char*& pOutput, int& nLenOutput)
{
	bool			bResult = false;
	TD_TLHEADER		hdr;
	RD_UINT8		uFinalKey[32];
	unsigned long	uFileSize = 0, uAllocated = 0, pos = 0;
	int				nEncryptedPartSize = 0;

	ASSERT(NULL != pInput);		if(NULL == pInput)		return FALSE;
	ASSERT(0	!= nLenInput);	if(0	== nLenInput)	return FALSE;
	ASSERT(NULL != szPassword); if(NULL == szPassword)	return FALSE;

	uFileSize = nLenInput + sizeof(TD_TLHEADER);

	// Allocate enough memory
	uAllocated = uFileSize + 16;
	pOutput = new unsigned char[uAllocated];
	if(NULL != pOutput)
	{
		unsigned long uKeyLen;

		// Build header structure
		hdr.dwSignature1 = TD_TLSIG_1;
		hdr.dwSignature2 = TD_TLSIG_2;
		hdr.dwKeyEncRounds = m_dwKeyEncRounds;

		// Make up the master key hash seed and the encryption IV
		m_random.GetRandomBuffer(hdr.aMasterSeed, 16);
		m_random.GetRandomBuffer((BYTE *)hdr.aEncryptionIV, 16);
		m_random.GetRandomBuffer(hdr.aMasterSeed2, 32);

		// Create MasterKey by hashing szPassword
		uKeyLen = strlen(szPassword);
		ASSERT(0 != uKeyLen);
		if(0 != uKeyLen)
		{
			sha256_ctx sha32;

			sha256_begin(&sha32);
			sha256_hash((unsigned char *)szPassword, uKeyLen, &sha32);
			sha256_end(m_pMasterKey, &sha32);

			// Generate m_pTransformedMasterKey from m_pMasterKey
			if(TRUE == _TransformMasterKey(hdr.aMasterSeed2))
			{
				// Hash the master password with the generated hash salt
				sha256_begin(&sha32);
				sha256_hash(hdr.aMasterSeed, 16, &sha32);
				sha256_hash(m_pTransformedMasterKey, 32, &sha32);
				sha256_end((unsigned char *)uFinalKey, &sha32);

				// Hash the tasklist contents
				sha256_begin(&sha32);
				sha256_hash((unsigned char *)pInput, nLenInput, &sha32);
				sha256_end((unsigned char *)hdr.aContentsHash, &sha32);

				// Hash the header
				sha256_begin(&sha32);
				sha256_hash((unsigned char *)&hdr + 32, sizeof(TD_TLHEADER) - 32, &sha32);
				sha256_end((unsigned char *)hdr.aHeaderHash, &sha32);
				
				bResult = true;
			}
		}
	}

	if (bResult)
	{
		bResult = false;
		
		// Now we have all to build up the header
		memcpy(pOutput, &hdr, sizeof(TD_TLHEADER));
	
		Rijndael aes;
		// Initialize Rijndael/AES
		if(RIJNDAEL_SUCCESS == aes.init(Rijndael::CBC, Rijndael::Encrypt, uFinalKey,
			Rijndael::Key32Bytes, hdr.aEncryptionIV) )
		{
			nEncryptedPartSize = aes.padEncrypt((RD_UINT8 *)pInput, nLenInput, (RD_UINT8 *)pOutput + sizeof(TD_TLHEADER));

			// Check if all went correct
			ASSERT(0 <= nEncryptedPartSize);
			if(0 <= nEncryptedPartSize)
			{
				bResult = true; // data encrypted successfully
			}

			nLenOutput = sizeof(TD_TLHEADER) + nEncryptedPartSize;
		}
	}

	if (!bResult)
	{
		SAFE_DELETE_ARRAY(pOutput);
	}

	return (bResult);
}
Beispiel #13
0
bool CEncryption::Decrypt(const unsigned char* pInput, int nLenInput, const char* szPassword,
						 unsigned char*& pOutput, int& nLenOutput)
{
	bool			bResult = false;
	TD_TLHEADER		hdr;
	RD_UINT8		uFinalKey[32];
	sha256_ctx		sha32;


	ASSERT(NULL != pInput);						if(NULL == pInput)					return FALSE;
	ASSERT(0	!= nLenInput);					if(0	== nLenInput)				return FALSE;
	ASSERT(NULL != szPassword);					if(NULL == szPassword)				return FALSE;
	ASSERT(sizeof(TD_TLHEADER) <= nLenInput);	if(sizeof(TD_TLHEADER) > nLenInput) return FALSE; 

	// Extract header structure from memory file
	memcpy(&hdr, pInput, sizeof(TD_TLHEADER));

	// Hash the header
	sha256_begin(&sha32);
	sha256_hash((unsigned char *)&hdr + 32, sizeof(TD_TLHEADER) - 32, &sha32);
	sha256_end((unsigned char *)uFinalKey, &sha32);

	// Check if hash of header is the same as stored hash
	// to verify integrity of header
	if(0 == memcmp(hdr.aHeaderHash, uFinalKey, 32))
	{
		// Check if we can open this
		if((hdr.dwSignature1 == TD_TLSIG_1) && (hdr.dwSignature2 == TD_TLSIG_2))
		{
			// Allocate enough memory
			pOutput = new unsigned char[nLenInput];
			if(NULL != pOutput)
			{
				unsigned long uKeyLen = strlen(szPassword);

				// Create MasterKey by hashing szPassword
				ASSERT(0 != uKeyLen);
				if(0 != uKeyLen)
				{
					sha256_begin(&sha32);
					sha256_hash((unsigned char *)szPassword, uKeyLen, &sha32);
					sha256_end(m_pMasterKey, &sha32);

					m_dwKeyEncRounds = hdr.dwKeyEncRounds;

					// Generate m_pTransformedMasterKey from m_pMasterKey
					if(TRUE == _TransformMasterKey(hdr.aMasterSeed2))
					{
						// Hash the master password with the generated hash salt
						sha256_begin(&sha32);
						sha256_hash(hdr.aMasterSeed, 16, &sha32);
						sha256_hash(m_pTransformedMasterKey, 32, &sha32);
						sha256_end((unsigned char *)uFinalKey, &sha32);

						bResult = true;
					}
				}
			}
		}
	}

	if (bResult)
	{
		bResult = false;

		Rijndael aes;
		// Initialize Rijndael/AES
		if(RIJNDAEL_SUCCESS == aes.init(Rijndael::CBC, Rijndael::Decrypt, uFinalKey,
			Rijndael::Key32Bytes, hdr.aEncryptionIV) )
		{
			nLenOutput = aes.padDecrypt((RD_UINT8 *)pInput + sizeof(TD_TLHEADER), nLenInput - sizeof(TD_TLHEADER), (RD_UINT8 *)pOutput);

			// Check if all went correct
			ASSERT(0 <= nLenOutput);
			if(0 <= nLenOutput)
			{
				// Check contents correct (with high probability)
				sha256_begin(&sha32);
				sha256_hash((unsigned char *)pOutput, nLenOutput, &sha32);
				sha256_end((unsigned char *)uFinalKey, &sha32);
				if(0 == memcmp(hdr.aContentsHash, uFinalKey, 32))
				{
					bResult = true; // data decrypted successfully
				}
			}
		}
	}

	if (!bResult)
	{
		SAFE_DELETE_ARRAY(pOutput);
	}

	return (bResult);
}
/* --------------------------------------------------------------------------
 * EcdsaSignerDoFinal
 * -------------------------------------------------------------------------- */
VLT_STS EcdsaSignerDoFinal(
    VLT_PU8 pu8Message, 
    VLT_U32 u32MessageLen, 
    VLT_U32 u32MessageCapacity, 
    VLT_PU8 pu8Signature, 
    VLT_PU32 pu32SignatureLen, 
    VLT_U32 u32SignatureCapacity )
{
	E2n_Point P;
	E2n_Point R;
	E2n_Point Q;

	/* intermediate calculation storage */
	DIGIT_T k[MAX_DIGITS];
	DIGIT_T k1[MAX_DIGITS]; 
	DIGIT_T	tmp[MAX_DIGITS];
	DIGIT_T r[MAX_DIGITS]; 
	DIGIT_T s[MAX_DIGITS]; 
	DIGIT_T u1[MAX_DIGITS];
	DIGIT_T u2[MAX_DIGITS]; 
	DIGIT_T v[MAX_DIGITS]; 
	DIGIT_T yy[MAX_DIGITS];

	DIGIT_T Px[MAX_DIGITS];
	DIGIT_T Py[MAX_DIGITS];

	DIGIT_T Rx[MAX_DIGITS];
	DIGIT_T Ry[MAX_DIGITS];

	DIGIT_T Qx[MAX_DIGITS];
	DIGIT_T Qy[MAX_DIGITS];

	/* SHA-256 storage */
	DIGIT_T	bdHash[MAX_DIGITS];
	VLT_U8 bHash[HASH_BYTE_SIZE];

	UINT len;
	UINT hashLen;

	sha256_ctx ctx; // context holder

    VLT_STS status = VLT_FAIL;

	if((ST_INITIALISED_SIGN != signerState) &&
	   (ST_INITIALISED_VERIFY != signerState))
	{
		/* not initialised */
		return EECDSAEXECUTIONERROR;
	}

	/* Initialise Point variables */
	P.x = Px;
	P.y = Py;
	R.x = Rx;
	R.y = Ry;
	Q.x = Qx;
	Q.y = Qy;

    if ( ( NULL == pu8Message ) ||
         ( NULL == pu8Signature ) ||
         ( NULL == pu32SignatureLen ) )
    {
        return ( EECDSAINUPNULLPARAM );
    }

	/* hash of message used by both signing and verify */

	/* e or e1 = SHA-256(M) */
	sha256_begin(&ctx);
    sha256_hash(pu8Message, u32MessageLen, &ctx);
    sha256_end(bHash, &ctx);

	/* convert hash to big digits, 
	same size as base point order if > hash size */
	if (sNumBpOrderDigits > HASH_DIGIT_SIZE)
		hashLen = sNumBpOrderDigits;
	else
		hashLen = HASH_DIGIT_SIZE;
	mpConvFromOctets(bdHash, hashLen, bHash, HASH_BYTE_SIZE);

	/* ANS X9.62-2005 7.3.e
	// if bit length of hash is > bit length of base point order
	// then truncate hash by removing LSBs until bit length
	// equals the length of the base point order
	*/
	len = mpBitLength(E.r, E.rlen);
	if (len < HASH_SIZE)
	{	
		/* take leftmost bits of message by shifting right */
		mpShiftRight(tmp, bdHash, HASH_SIZE - len, hashLen);
		/* truncate to base point order size */
		mpSetEqual(bdHash, tmp, E.rlen);
	}

	if (ST_INITIALISED_SIGN == signerState)
	{
		/* signing process as per ANS X9.62 Section 7.3 */
		*pu32SignatureLen = 0;

		/* generate ephemeral private key k such that 0 < k < n */			 
		if (VLT_OK != GenerateRandomDigits(tmp, E.rlen))
			return EECDSAEXECUTIONERROR;
		mpModulo(k, tmp, E.rlen, E.r, E.rlen);
		if (mpIsZero(k, E.rlen))
		{
			/* probability of a zero is 1/n */
			if (VLT_OK != GenerateRandomDigits(tmp, E.rlen))
				return EECDSAEXECUTIONERROR;
			mpModulo(k, tmp, E.rlen, E.r, E.rlen);
			if (mpIsZero(k, E.rlen))
			{
				return EECDSAEXECUTIONERROR;
			}
		}

		/* generate ephemeral public key: P = kG */
		e2n_point_mul(&E, &P, &E.G, k, E.rlen);

		/* convert P.x to integer j	*/
		/* conversion is implicit for polynomial basis */

		/*
		// r = j mod n, n = base point oder (E.r)
		*/
		mpModulo(r, P.x, E.rlen, E.r, E.rlen);

		/*
		// calculate s = k^-1 (e + dr) mod n
		*/

		/* Compute k' = k^-1 mod n */
		mpModInv(k1, k, E.r, E.rlen);

		/* Compute s = (k^-1(SHA-xxx(M) + dr)) mod n */

		/* d * r */
		mpModMult(tmp, sPrivateKey, r, E.r, E.rlen);
		/* M + d * r */
		mpModAdd(yy, tmp, bdHash, E.r, E.rlen);
		/* s = (k^-1)(M + dr) */
		mpModMult(s, k1, yy, E.r, E.rlen);
	
		/* signing: convert back to byte format and construct r || s */
		mpConvToOctets(r, sNumBpOrderDigits, pu8Signature, sNumBpOrderBytes);
		mpConvToOctets(s, sNumBpOrderDigits, pu8Signature + sNumBpOrderBytes, 
			sNumBpOrderBytes);

		/* set the byte length of the output signature */
		*pu32SignatureLen = sNumBpOrderBytes * 2;

		status = VLT_OK;
	}
	else
	{
	    /* ANS X9.62-2005 Section 7.4.1: Verification with Public Key */;

		/* extract r & s and format as big digits */
		mpConvFromOctets(r, E.rlen, pu8Signature, (*pu32SignatureLen) / 2);
		mpConvFromOctets(s, E.rlen, pu8Signature + (*pu32SignatureLen / 2), 
			(*pu32SignatureLen) / 2);

		/* Compute u1 = e1(s1^-1) mod n */
		mpModInv(tmp, s, E.r, E.rlen);
		mpModMult(u1, tmp, bdHash, E.r, E.rlen);

		/* Compute u2 = r1(s1^-1) mod n */
		mpModMult(u2, tmp, r, E.r, E.rlen);

		/* use supplied public key */
		mpSetEqual(Q.x, sPublicKeyQx, E.len);
		mpSetEqual(Q.y, sPublicKeyQy, E.len);

		/* compute R = u1G */
		e2n_point_mul(&E, &R, &E.G, u1, E.rlen);

		/* P = u2Q */
		e2n_point_mul(&E, &P, &Q, u2, E.rlen);

		/* R = R + P */
		e2n_point_add(&E, &R, &R, &P);

		/* compute v = j mod n */
		mpModulo(v, R.x, E.rlen, E.r, E.rlen);

		/* verify v == r */
		if (mpEqual(v, r, E.rlen))
		{	
			status = VLT_OK;
		}
		else
		{
			status = VLT_FAIL;
		}
	}

    return ( status );
}
Beispiel #15
0
int CHashManager::HashFile(char *pszFile)
{
	FILE *fp = NULL;
	unsigned char pBuf[SIZE_HASH_BUFFER];
	unsigned long uRead = 0;
	unsigned char pTemp[256];
	char szTemp[RH_MAX_BUFFER];
	int i = 0;

	printf("File: <");
	printf(pszFile);
	printf(">");
	printf(CPS_NEWLINE);

	fp = fopen(pszFile, "rb");
	if(fp == NULL) return RH_CANNOT_OPEN_FILE;

	if(m_bAlgorithm[HASHID_CRC16]) crc16_init(&m_crc16);
	if(m_bAlgorithm[HASHID_CRC16CCITT]) crc16ccitt_init(&m_crc16ccitt);
	if(m_bAlgorithm[HASHID_CRC32]) crc32Init(&m_crc32);
	if(m_bAlgorithm[HASHID_FCS_16]) fcs16_init(&m_fcs16);
	if(m_bAlgorithm[HASHID_FCS_32]) fcs32_init(&m_fcs32);
	if(m_bAlgorithm[HASHID_GHASH_32_3] || m_bAlgorithm[HASHID_GHASH_32_5]) m_ghash.Init();
	if(m_bAlgorithm[HASHID_GOST]) gosthash_reset(&m_gost);
	if(m_bAlgorithm[HASHID_HAVAL]) haval_start(&m_haval);
	if(m_bAlgorithm[HASHID_MD2]) m_md2.Init();
	if(m_bAlgorithm[HASHID_MD4]) MD4Init(&m_md4);
	if(m_bAlgorithm[HASHID_MD5]) MD5Init(&m_md5, 0);
	if(m_bAlgorithm[HASHID_SHA1]) sha1_begin(&m_sha1);
	if(m_bAlgorithm[HASHID_SHA2_256]) sha256_begin(&m_sha256);
	if(m_bAlgorithm[HASHID_SHA2_384]) sha384_begin(&m_sha384);
	if(m_bAlgorithm[HASHID_SHA2_512]) sha512_begin(&m_sha512);
	if(m_bAlgorithm[HASHID_SIZE_32]) sizehash32_begin(&m_uSizeHash32);
	if(m_bAlgorithm[HASHID_TIGER]) tiger_init(&m_tiger);

	while(1)
	{
		uRead = fread(pBuf, 1, SIZE_HASH_BUFFER, fp);

		if(uRead != 0)
		{
			if(m_bAlgorithm[HASHID_CRC16])
				crc16_update(&m_crc16, pBuf, uRead);

			if(m_bAlgorithm[HASHID_CRC16CCITT])
				crc16ccitt_update(&m_crc16ccitt, pBuf, uRead);

			if(m_bAlgorithm[HASHID_CRC32])
				crc32Update(&m_crc32, pBuf, uRead);

			if(m_bAlgorithm[HASHID_FCS_16])
				fcs16_update(&m_fcs16, pBuf, uRead);

			if(m_bAlgorithm[HASHID_FCS_32])
				fcs32_update(&m_fcs32, pBuf, uRead);

			if(m_bAlgorithm[HASHID_GHASH_32_3] || m_bAlgorithm[HASHID_GHASH_32_5])
				m_ghash.Update(pBuf, uRead);

			if(m_bAlgorithm[HASHID_GOST])
				gosthash_update(&m_gost, pBuf, uRead);

			if(m_bAlgorithm[HASHID_HAVAL])
				haval_hash(&m_haval, pBuf, uRead);

			if(m_bAlgorithm[HASHID_MD2])
				m_md2.Update(pBuf, uRead);

			if(m_bAlgorithm[HASHID_MD4])
				MD4Update(&m_md4, pBuf, uRead);

			if(m_bAlgorithm[HASHID_MD5])
				MD5Update(&m_md5, pBuf, uRead);

			if(m_bAlgorithm[HASHID_SHA1])
				sha1_hash(pBuf, uRead, &m_sha1);

			if(m_bAlgorithm[HASHID_SHA2_256])
				sha256_hash(pBuf, uRead, &m_sha256);

			if(m_bAlgorithm[HASHID_SHA2_384])
				sha384_hash(pBuf, uRead, &m_sha384);

			if(m_bAlgorithm[HASHID_SHA2_512])
				sha512_hash(pBuf, uRead, &m_sha512);

			if(m_bAlgorithm[HASHID_SIZE_32])
				sizehash32_hash(&m_uSizeHash32, uRead);

			if(m_bAlgorithm[HASHID_TIGER])
				tiger_process(&m_tiger, pBuf, uRead);
		}

		if(uRead != SIZE_HASH_BUFFER) break;
	}

	fclose(fp); fp = NULL;

	// SizeHash-32 is the first hash, because it's the simplest one,
	// the fastest, and most widely used one. ;-)
	if(m_bAlgorithm[HASHID_SIZE_32])
	{
		sizehash32_end(&m_uSizeHash32);
		printf(SZ_SIZEHASH_32);
		printf(SZ_HASHPRE);

		printf("%08X", m_uSizeHash32);

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_CRC16])
	{
		crc16_final(&m_crc16);
		printf(SZ_CRC16);
		printf(SZ_HASHPRE);

		printf("%04X", m_crc16);

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_CRC16CCITT])
	{
		crc16ccitt_final(&m_crc16ccitt);
		printf(SZ_CRC16CCITT);
		printf(SZ_HASHPRE);

		printf("%04X", m_crc16ccitt);

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_CRC32])
	{
		crc32Finish(&m_crc32);
		printf(SZ_CRC32);
		printf(SZ_HASHPRE);

		printf("%08X", m_crc32);

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_FCS_16])
	{
		fcs16_final(&m_fcs16);
		printf(SZ_FCS_16);
		printf(SZ_HASHPRE);

		printf("%04X", m_fcs16);

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_FCS_32])
	{
		fcs32_final(&m_fcs32);
		printf(SZ_FCS_32);
		printf(SZ_HASHPRE);

		printf("%08X", m_fcs32);

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_GHASH_32_3])
	{
		m_ghash.FinalToStr(szTemp, 3);
		printf(SZ_GHASH_32_3);
		printf(SZ_HASHPRE);

		printf(szTemp);

		printf(CPS_NEWLINE);
	}
	if(m_bAlgorithm[HASHID_GHASH_32_5])
	{
		m_ghash.FinalToStr(szTemp, 5);
		printf(SZ_GHASH_32_5);
		printf(SZ_HASHPRE);

		printf(szTemp);

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_GOST])
	{
		gosthash_final(&m_gost, pTemp);
		printf(SZ_GOST);
		printf(SZ_HASHPRE);

		for(i = 0; i < 32; i++)
		{
			fmtFixHashOutput(i);
			printf("%02X", pTemp[i]);
		}

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_HAVAL])
	{
		haval_end(&m_haval, pTemp);
		printf(SZ_HAVAL);
		printf(SZ_HASHPRE);

		for(i = 0; i < 32; i++)
		{
			fmtFixHashOutput(i);
			printf("%02X", pTemp[i]);
		}

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_MD2])
	{
		m_md2.TruncatedFinal(pTemp, 16);
		printf(SZ_MD2);
		printf(SZ_HASHPRE);

		for(i = 0; i < 16; i++)
		{
			fmtFixHashOutput(i);
			printf("%02X", pTemp[i]);
		}

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_MD4])
	{
		MD4Final(pTemp, &m_md4);
		printf(SZ_MD4);
		printf(SZ_HASHPRE);

		for(i = 0; i < 16; i++)
		{
			fmtFixHashOutput(i);
			printf("%02X", pTemp[i]);
		}

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_MD5])
	{
		MD5Final(&m_md5);
		printf(SZ_MD5);
		printf(SZ_HASHPRE);

		for(i = 0; i < 16; i++)
		{
			fmtFixHashOutput(i);
			printf("%02X", m_md5.digest[i]);
		}

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_SHA1])
	{
		sha1_end(pTemp, &m_sha1);
		printf(SZ_SHA1);
		printf(SZ_HASHPRE);

		for(i = 0; i < 20; i++)
		{
			fmtFixHashOutput(i);
			printf("%02X", pTemp[i]);
		}

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_SHA2_256])
	{
		sha256_end(pTemp, &m_sha256);
		printf(SZ_SHA2_256);
		printf(SZ_HASHPRE);

		for(i = 0; i < 32; i++)
		{
			fmtFixHashOutput(i);
			printf("%02X", pTemp[i]);
		}

		printf(CPS_NEWLINE);
	}
	if(m_bAlgorithm[HASHID_SHA2_384])
	{
		sha384_end(pTemp, &m_sha384);
		printf(SZ_SHA2_384);
		printf(SZ_HASHPRE);

		for(i = 0; i < 48; i++)
		{
			fmtFixHashOutput(i);
			printf("%02X", pTemp[i]);
		}

		printf(CPS_NEWLINE);
	}
	if(m_bAlgorithm[HASHID_SHA2_512])
	{
		sha512_end(pTemp, &m_sha512);
		printf(SZ_SHA2_512);
		printf(SZ_HASHPRE);

		for(i = 0; i < 64; i++)
		{
			fmtFixHashOutput(i);
			printf("%02X", pTemp[i]);
		}

		printf(CPS_NEWLINE);
	}

	if(m_bAlgorithm[HASHID_TIGER])
	{
		tiger_done(&m_tiger, pTemp);
		printf(SZ_TIGER);
		printf(SZ_HASHPRE);

		for(i = 0; i < 8; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[7-i]); }
		for(i = 8; i < 16; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[23-i]); }
		for(i = 16; i < 24; i++) { fmtFixHashOutput(i); printf("%02X", pTemp[39-i]); }

		printf(CPS_NEWLINE);
	}

	return RH_SUCCESS;
}
Beispiel #16
0
BOOL CPwCompatImpl::OpenDatabaseV1(CPwManager* pMgr, const TCHAR *pszFile)
{
	FILE *fp;
	char *pVirtualFile;
	unsigned long uFileSize, uAllocated, uEncryptedPartSize;
	size_t i, j, pos;
	PW_DBHEADER_V1 hdr;
	sha256_ctx sha32;
	UINT8 uFinalKey[32];
	DWORD dw, dw2;
	char *ptrTemp;
	char *ptrTitle;
	char *ptrUserName;
	char *ptrURL;
	char *ptrPassword;
	char *ptrAdditional;
	PW_TIME tNow;
	PW_GROUP pwTG;
	PW_ENTRY pwTE;

	_GetCurrentPwTime(&tNow);
	memset(&pwTG, 0, sizeof(PW_GROUP));
	memset(&pwTE, 0, sizeof(PW_ENTRY));
	pwTG.tCreation = tNow; pwTG.tExpire = g_pwTimeNever;
	pwTG.tLastAccess = tNow; pwTG.tLastMod = tNow;
	pwTE.tCreation = tNow; pwTE.tExpire = g_pwTimeNever;
	pwTE.tLastAccess = tNow; pwTE.tLastMod = tNow;

	ASSERT(sizeof(char) == 1);

	ASSERT(pszFile != NULL);
	if(pszFile == NULL) return FALSE;
	ASSERT(_tcslen(pszFile) != 0);
	if(_tcslen(pszFile) == 0) return FALSE;

	fp = NULL;
	_tfopen_s(&fp, pszFile, _T("rb"));
	if(fp == NULL) return FALSE;

	// Get file size
	fseek(fp, 0, SEEK_END);
	uFileSize = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	if(uFileSize < sizeof(PW_DBHEADER_V1))
		{ fclose(fp); return FALSE; }

	// Allocate enough memory to hold the complete file
	uAllocated = uFileSize + 17;
	pVirtualFile = new char[uAllocated];
	if(pVirtualFile == NULL)
		{ fclose(fp); return FALSE; }
	pVirtualFile[uFileSize + 17 - 1] = 0;
	fread(pVirtualFile, 1, uFileSize, fp);
	fclose(fp);

	// Extract header structure from memory file
	memcpy(&hdr, pVirtualFile, sizeof(PW_DBHEADER_V1));

	// Check if we can open this
	if((hdr.dwSignature1 != PWM_DBSIG_1) || (hdr.dwSignature2 != PWM_DBSIG_2))
		{ _OPENDB_FAIL; }

	if((hdr.dwFlags & PWM_FLAG_RIJNDAEL) != 0) pMgr->SetAlgorithm(ALGO_AES);
	else if((hdr.dwFlags & PWM_FLAG_TWOFISH) != 0) pMgr->SetAlgorithm(ALGO_TWOFISH);
	else { ASSERT(FALSE); _OPENDB_FAIL; }

	BYTE aMasterKeyU[32];
	pMgr->GetRawMasterKey(aMasterKeyU);

	// Hash the master password with the salt in the file
	sha256_begin(&sha32);
	sha256_hash(hdr.aMasterSeed, 16, &sha32);
	sha256_hash(aMasterKeyU, 32, &sha32);
	sha256_end((unsigned char *)uFinalKey, &sha32);

	mem_erase(aMasterKeyU, 32);

	if(pMgr->GetAlgorithm() == ALGO_AES)
	{
		CRijndael aes;

		// Initialize Rijndael algorithm
		if(aes.Init(CRijndael::CBC, CRijndael::DecryptDir, uFinalKey,
			CRijndael::Key32Bytes, hdr.aEncryptionIV) != RIJNDAEL_SUCCESS)
			{ _OPENDB_FAIL; }

		// Decrypt! The first 48 bytes aren't encrypted (that's the header)
		uEncryptedPartSize = (unsigned long)aes.PadDecrypt((UINT8 *)pVirtualFile + 48,
			uFileSize - 48, (UINT8 *)pVirtualFile + 48);
	}
	else if(pMgr->GetAlgorithm() == ALGO_TWOFISH)
	{
		CTwofish twofish;

		if(twofish.Init(uFinalKey, 32, hdr.aEncryptionIV) != true)
			{ _OPENDB_FAIL };

		uEncryptedPartSize = (unsigned long)twofish.PadDecrypt(
			(UINT8 *)pVirtualFile + 48,
			uFileSize - 48, (UINT8 *)pVirtualFile + 48);
	}
STDMETHODIMP CKpUtilitiesImpl::SHA256Final(void* pContext, BYTE* pOutHashBuf)
{
	if((pContext == NULL) || (pOutHashBuf == NULL)) return E_POINTER;
	sha256_end(pOutHashBuf, (sha256_ctx*)pContext);
	return S_OK;
}
Beispiel #18
0
	void Sha256::GetDigest (const BufferPtr &buffer)
	{
		if_debug (ValidateDigestParameters (buffer));
		sha256_end (buffer, (sha256_ctx *) Context.Ptr());
	}
Beispiel #19
0
// If bIgnoreCorrupted is TRUE the manager will try to ignore all database file
// errors, i.e. try to read as much as possible instead of breaking out at the
// first error.
// To open a file normally, set bIgnoreCorrupted to FALSE (default).
// To open a file in rescue mode, set it to TRUE.
int CPwManager::OpenDatabase(const TCHAR *pszFile, _Out_opt_ PWDB_REPAIR_INFO *pRepair)
{
	char *pVirtualFile;
	unsigned long uFileSize, uAllocated, uEncryptedPartSize;
	unsigned long pos;
	PW_DBHEADER hdr;
	sha256_ctx sha32;
	UINT8 uFinalKey[32];
	char *p;
	USHORT usFieldType;
	DWORD dwFieldSize;
	PW_GROUP pwGroupTemplate;
	PW_ENTRY pwEntryTemplate;

	BOOST_STATIC_ASSERT(sizeof(char) == 1);

	ASSERT(pszFile != NULL); if(pszFile == NULL) return PWE_INVALID_PARAM;
	ASSERT(pszFile[0] != 0); if(pszFile[0] == 0) return PWE_INVALID_PARAM; // Length != 0

	RESET_PWG_TEMPLATE(&pwGroupTemplate);
	RESET_PWE_TEMPLATE(&pwEntryTemplate);

	if(pRepair != NULL) { ZeroMemory(pRepair, sizeof(PWDB_REPAIR_INFO)); }

	FILE *fp = NULL;
	_tfopen_s(&fp, pszFile, _T("rb"));
	if(fp == NULL) return PWE_NOFILEACCESS_READ;

	// Get file size
	fseek(fp, 0, SEEK_END);
	uFileSize = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	if(uFileSize < sizeof(PW_DBHEADER))
		{ fclose(fp); return PWE_INVALID_FILEHEADER; }

	// Allocate enough memory to hold the complete file
	uAllocated = uFileSize + 16 + 1 + 64 + 4; // 16 = encryption buffer space, 1+64 = string terminating NULLs, 4 unused
	pVirtualFile = new char[uAllocated];
	if(pVirtualFile == NULL) { fclose(fp); return PWE_NO_MEM; }
	memset(&pVirtualFile[uFileSize + 16], 0, 1 + 64);

	fread(pVirtualFile, 1, uFileSize, fp);
	fclose(fp);

	// Extract header structure from memory file
	memcpy(&hdr, pVirtualFile, sizeof(PW_DBHEADER));

	// Check if it's a KDBX file created by KeePass 2.x
	if((hdr.dwSignature1 == PWM_DBSIG_1_KDBX_P) && (hdr.dwSignature2 == PWM_DBSIG_2_KDBX_P))
		{ _OPENDB_FAIL_LIGHT; return PWE_UNSUPPORTED_KDBX; }
	if((hdr.dwSignature1 == PWM_DBSIG_1_KDBX_R) && (hdr.dwSignature2 == PWM_DBSIG_2_KDBX_R))
		{ _OPENDB_FAIL_LIGHT; return PWE_UNSUPPORTED_KDBX; }

	// Check if we can open this
	if((hdr.dwSignature1 != PWM_DBSIG_1) || (hdr.dwSignature2 != PWM_DBSIG_2))
		{ _OPENDB_FAIL_LIGHT; return PWE_INVALID_FILESIGNATURE; }

	if((hdr.dwVersion & 0xFFFFFF00) != (PWM_DBVER_DW & 0xFFFFFF00))
	{
		if((hdr.dwVersion == 0x00020000) || (hdr.dwVersion == 0x00020001) || (hdr.dwVersion == 0x00020002))
		{
			if(pVirtualFile != NULL)
			{
				mem_erase((unsigned char *)pVirtualFile, uAllocated);
				SAFE_DELETE_ARRAY(pVirtualFile);
			}

			return ((CPwCompatImpl::OpenDatabaseV2(this, pszFile) != FALSE) ?
				PWE_SUCCESS : PWE_UNKNOWN);
		}
		else if(hdr.dwVersion <= 0x00010002)
		{
			if(pVirtualFile != NULL)
			{
				mem_erase((unsigned char *)pVirtualFile, uAllocated);
				SAFE_DELETE_ARRAY(pVirtualFile);
			}
			
			return ((CPwCompatImpl::OpenDatabaseV1(this, pszFile) != FALSE) ?
				PWE_SUCCESS : PWE_UNKNOWN);
		}
		else { ASSERT(FALSE); _OPENDB_FAIL; }
	}

	if(hdr.dwGroups == 0) { _OPENDB_FAIL_LIGHT; return PWE_DB_EMPTY; }

	// Select algorithm
	if((hdr.dwFlags & PWM_FLAG_RIJNDAEL) != 0) m_nAlgorithm = ALGO_AES;
	else if((hdr.dwFlags & PWM_FLAG_TWOFISH) != 0) m_nAlgorithm = ALGO_TWOFISH;
	else { ASSERT(FALSE); _OPENDB_FAIL; }

	m_dwKeyEncRounds = hdr.dwKeyEncRounds;

	// Generate m_pTransformedMasterKey from m_pMasterKey
	if(_TransformMasterKey(hdr.aMasterSeed2) == FALSE) { ASSERT(FALSE); _OPENDB_FAIL; }

	ProtectTransformedMasterKey(false);

	// Hash the master password with the salt in the file
	sha256_begin(&sha32);
	sha256_hash(hdr.aMasterSeed, 16, &sha32);
	sha256_hash(m_pTransformedMasterKey, 32, &sha32);
	sha256_end((unsigned char *)uFinalKey, &sha32);

	ProtectTransformedMasterKey(true);

	if(pRepair == NULL)
	{
		// ASSERT(((uFileSize - sizeof(PW_DBHEADER)) % 16) == 0);
		if(((uFileSize - sizeof(PW_DBHEADER)) % 16) != 0)
		{
			_OPENDB_FAIL_LIGHT;
			return PWE_INVALID_FILESIZE;
		}
	}
	else // Repair the database
	{
		if(((uFileSize - sizeof(PW_DBHEADER)) % 16) != 0)
		{
			uFileSize -= sizeof(PW_DBHEADER); ASSERT((uFileSize & 0xF) != 0);
			uFileSize &= ~0xFUL;
			uFileSize += sizeof(PW_DBHEADER);
		}

		ASSERT(((uFileSize - sizeof(PW_DBHEADER)) % 16) == 0);

		pRepair->dwOriginalGroupCount = hdr.dwGroups;
		pRepair->dwOriginalEntryCount = hdr.dwEntries;
	}

	if(m_nAlgorithm == ALGO_AES)
	{
		CRijndael aes;

		// Initialize Rijndael algorithm
		if(aes.Init(CRijndael::CBC, CRijndael::DecryptDir, uFinalKey,
			CRijndael::Key32Bytes, hdr.aEncryptionIV) != RIJNDAEL_SUCCESS)
			{ _OPENDB_FAIL_LIGHT; return PWE_CRYPT_ERROR; }

		// Decrypt! The first bytes aren't encrypted (that's the header)
		uEncryptedPartSize = (unsigned long)aes.PadDecrypt((UINT8 *)pVirtualFile + sizeof(PW_DBHEADER),
			uFileSize - sizeof(PW_DBHEADER), (UINT8 *)pVirtualFile + sizeof(PW_DBHEADER));
	}
	else if(m_nAlgorithm == ALGO_TWOFISH)
	{
		CTwofish twofish;

		if(twofish.Init(uFinalKey, 32, hdr.aEncryptionIV) != true)
			{ _OPENDB_FAIL };

		uEncryptedPartSize = (unsigned long)twofish.PadDecrypt((UINT8 *)pVirtualFile + sizeof(PW_DBHEADER),
			uFileSize - sizeof(PW_DBHEADER), (UINT8 *)pVirtualFile + sizeof(PW_DBHEADER));
	}