Exemple #1
0
// Helper function for multithreaded key transformation
PwDatabase::ErrorCode PwDatabase::performKeyTransformRounds(const unsigned char* pTransformSeed,
        unsigned char* pTransKey, const quint64 nRounds, bool reportProgress) {
    // make a local copy of the subkey and the key
    unsigned char transKey[SUBKEY_SIZE];
    unsigned char key[32];
    memcpy(transKey, pTransKey, SUBKEY_SIZE);
    memcpy(key, pTransformSeed, 32);

    // prepare key transform
    Rijndael aes;
    int ec = (qint8)aes.init(Rijndael::ECB, Rijndael::Encrypt, key, Rijndael::Key32Bytes, 0);
    if (ec != RIJNDAEL_SUCCESS) {
        LOG("Rijndael init error %d", ec);
        return KEY_TRANSFORM_INIT_ERROR;
    }

    if (reportProgress) {
        for (quint64 round = 0; round < nRounds; round++) {
            setProgress(round);
            aes.encrypt(transKey, transKey); // only works with 16-byte buffers
        }
    } else {
        for (quint64 round = 0; round < nRounds; round++) {
            aes.encrypt(transKey, transKey); // only works with 16-byte buffers
        }
    }
    memcpy(pTransKey, transKey, SUBKEY_SIZE);
    return SUCCESS;
}
//! On entry the current value of m_mac becomes the initialization vector
//! for the CBC encryption of this block. The output of the encryption then
//! becomes the new MAC, which is stored in m_mac.
void RijndaelCBCMAC::updateOneBlock(const uint8_t *data)
{
    Rijndael cipher;
    cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_key, Rijndael::Key16Bytes, m_mac);
    cipher.blockEncrypt(data, BLOCK_SIZE * 8, m_mac); // size is in bits

    //	Log::log(Logger::DEBUG2, "CBC-MAC output block:\n");
    //	logHexArray(Logger::DEBUG2, (const uint8_t *)&m_mac, sizeof(m_mac));
}
Exemple #3
0
bool AES_CBC_Decode(const unsigned char* key, int keyLen, unsigned char* initVector, const unsigned char* input, int inputOctets, unsigned char* outBuffer)
{
	Rijndael oRijndael;

	oRijndael.init(Rijndael::CBC, Rijndael::Decrypt, key, static_cast<Rijndael::KeyLength>(keyLen), initVector);

	int nLength = oRijndael.padDecrypt(input, inputOctets, outBuffer);	

	return (nLength > 0)?true:false;
}
Exemple #4
0
int main()   
{   
	RD_UINT8 inputBuf[256], passwd[16], Encrypted[512], Decrypted[256], *pch;   
	int ix, iLen; 
	
	while(1)   
	{   
		printf("Please enter your plain code and press the Enter: \n");   
		fgets((char*)inputBuf, sizeof(inputBuf), stdin);   
		for (ix = strlen((char*)inputBuf) - 1; (ix >= 0) && (inputBuf[ix] == 10); ix--)   
		inputBuf[ix] = 0;   
		if (!inputBuf[0])   
		break;   
		printf("\nPlease enter the key: ");   
		fgets((char*)passwd, sizeof(passwd), stdin);   
		for (ix = strlen((char*)passwd) - 1; (ix >= 0) && (passwd[ix] == 10); ix--)   
		passwd[ix] = 0;   
		if (!passwd[0])   
		break;   
		iLen = strlen((char*)inputBuf); 
		//int init (Mode mode,Direction dir,const RD_UINT8 *key,KeyLength keyLen,RD_UINT8 * initVector = 0);
		Rijndael zts;
		//zts.init (Rijndael::ECB, Rijndael::Encrypt, passwd, Rijndael::Key16Bytes);
		//zts.init (Rijndael::ECB, (Rijndael::Direction)0, passwd, (Rijndael::KeyLength)0, (RD_UINT8*)0);
		//int blockEncrypt(const RD_UINT8 *input, int inputLen, RD_UINT8 *outBuffer);
		
		zts.blockEncrypt (inputBuf, iLen, Encrypted);
		printf("\n¼ÓÃܺó:\n");   
		for (pch = Encrypted, ix=0; ix < (iLen*2); pch++, ix++)   
        {   
            if (!(ix % 20))   
                printf("\n");   
            printf("%X ", (unsigned char)*pch);   
        }   
		//int blockDecrypt(const RD_UINT8 *input, int inputLen, RD_UINT8 *outBuffer);
		//zts.init (Rijndael::ECB, Rijndael::Decrypt, passwd, Rijndael::Key16Bytes);
		//zts.init ((Rijndael::Mode)0, (Rijndael::Direction)1, passwd, (Rijndael::KeyLength)0, (RD_UINT8*)0);
		zts.blockDecrypt (Encrypted, iLen*2, Decrypted); 
        Decrypted[iLen] = 0;     
        printf("\n½âÃÜºó£º %s\n", Decrypted);   
        

    }   
    return 0;   
}   
Exemple #5
0
// Test CBC encryption according to NIST 800-38A.
void TestRijndael()
{
  byte IV[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
  byte PT[64]={
    0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,
    0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51,
    0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef,
    0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10,
  };

  byte Key128[16]={0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c};
  byte Chk128[16]={0x3f,0xf1,0xca,0xa1,0x68,0x1f,0xac,0x09,0x12,0x0e,0xca,0x30,0x75,0x86,0xe1,0xa7};
  byte Key192[24]={0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52,0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5,0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b};
  byte Chk192[16]={0x08,0xb0,0xe2,0x79,0x88,0x59,0x88,0x81,0xd9,0x20,0xa9,0xe6,0x4f,0x56,0x15,0xcd};
  byte Key256[32]={0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4};
  byte Chk256[16]={0xb2,0xeb,0x05,0xe2,0xc3,0x9b,0xe9,0xfc,0xda,0x6c,0x19,0x07,0x8c,0x6a,0x9d,0x1b};
  byte *Key[3]={Key128,Key192,Key256};
  byte *Chk[3]={Chk128,Chk192,Chk256};

  Rijndael rij; // Declare outside of loop to test re-initialization.
  for (uint L=0;L<3;L++)
  {
    byte Out[16];
    wchar Str[sizeof(Out)*2+1];

    uint KeyLength=128+L*64;
    rij.Init(true,Key[L],KeyLength,IV);
    for (uint I=0;I<sizeof(PT);I+=16)
      rij.blockEncrypt(PT+I,16,Out);
    BinToHex(Chk[L],16,NULL,Str,ASIZE(Str));
    mprintf(L"\nAES-%d expected: %s",KeyLength,Str);
    BinToHex(Out,sizeof(Out),NULL,Str,ASIZE(Str));
    mprintf(L"\nAES-%d result:   %s",KeyLength,Str);
    if (memcmp(Out,Chk[L],16)==0)
      mprintf(L" OK");
    else
    {
      mprintf(L" FAILED");
      getchar();
    }
  }
}
Exemple #6
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;
}
int main(){  

	unsigned int* iter;
	unsigned char mClaveExp[176]; // contendra la expansion de clave	
	unsigned char clave[16] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; //clave    
   	unsigned char arrTexto[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}; // texto a cifrar    
	char resp;
	unsigned char texto[4][4]; // matriz 4x4 texto a cifrar
	unsigned char mClave[4][4]; //matriz 4x4 clave
	
	system("clear");
                 	
	cout << "********************************************************************************************"<< endl;
	cout << "*                                      RIJNDAEL                                    *" << endl;
	cout << "********************************************************************************************" << endl << endl;
	
	cout << "CLAVE: ";
	for (int i = 0; i < 16; i++){
		printf(" %02x ",clave[i]);
	} 
	cout << "\nTEXTO: ";
	for (int i = 0; i < 16; i++){
		printf(" %02x ",arrTexto[i]);
	}
  
	cout << "\nDESEA MODIFICAR LOS DATOS:(S/N):";
	cin >> resp;
	cin.clear(); //limpiamos buffer
	fflush(stdin);

	if(resp == 's' || resp == 'S') { 	

	cout << "CLAVE EN HEXADECIMAL: ";
	for(int i = 0; i < 16; i++){	
	
		scanf("%02x",&clave[i]);
	}
	cin.clear(); //limpiamos buffer
	fflush(stdin);
 
	cout << "TEXTO EN HEXAMECIMAL: ";
	for(int i = 0; i < 16; i++){
		scanf("%02x",&arrTexto[i]);
	}
 	cin.clear();  //limpiamos buffer
	fflush(stdin);
    	}
	
	cout << "\n\n********************************************************************************************"<< endl;
	
	for (int i = 0; i < 4; i++){
	    for (int j = 0; j < 4; j++){
            	mClave[j][i] = clave[i*4 + j]; // convierte clave a cifrar en una matriz 4X4
            }
    	}
	
	for (int i = 0; i < 4; i++){
	    for (int j = 0; j < 4; j++){
            	texto[j][i] = arrTexto[i*4 + j]; // texto a cifrar en una matriz 4X4
            }
    	}

    	Rijndael aes; 
	aes.expandirClave(mClave, mClaveExp);  //expandir la clave y guardarla en un array
    	aes.encriptar(texto, mClaveExp);  //ciframos el texto
    	cout << "\n\n\n********************************************************************************************"<< endl;
    	
    	for (int i = 0; i < 4; i++){
	    for (int j = 0; j < 4; j++){
	        printf(" %02x ",texto[j][i]); 
	    }
    	}
    	cout << "\n********************************************************************************************"<< endl;
    	cout << "\n\n\n\n";
	//iter = A.devIteraciones();
	//printf(" %02x ",iter[0]);
        
}
Exemple #8
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);
}
Exemple #9
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);
}
//! \todo Optimize writing section data. Right now it only writes one block at a
//!		time, which is of course quite slow (in relative terms).
//!	\todo Refactor this into several different methods for writing each region
//!		of the image. Use a context structure to keep track of shared data between
//!		each of the methods.
//! \todo Refactor the section and boot tag writing code to only have a single
//!		copy of the block writing and encryption loop.
void EncoreBootImage::writeToStream(std::ostream & stream)
{
	// always generate the session key or DEK even if image is unencrypted
	m_sessionKey.randomize();
	
	// prepare to compute CBC-MACs with each KEK
	unsigned i;
	smart_array_ptr<RijndaelCBCMAC> macs(0);
	if (isEncrypted())
	{
		macs = new RijndaelCBCMAC[m_keys.size()];
		for (i=0; i < m_keys.size(); ++i)
		{
			RijndaelCBCMAC mac(m_keys[i]);
			(macs.get())[i] = mac;
		}
	}
	
	// prepare to compute SHA-1 digest over entire image
	CSHA1 hash;
	hash.Reset();
	
	// count of total blocks written to the file
	unsigned fileBlocksWritten = 0;

	// we need some pieces of the header down below
	boot_image_header_t imageHeader;
	prepareImageHeader(imageHeader);
	
	// write plaintext header
	{
		// write header
		assert(sizeOfPaddingForCipherBlocks(sizeof(boot_image_header_t)) == 0);
		stream.write(reinterpret_cast<char *>(&imageHeader), sizeof(imageHeader));
		fileBlocksWritten += numberOfCipherBlocks(sizeof(imageHeader));
		
		// update CBC-MAC over image header
		if (isEncrypted())
		{
			for (i=0; i < m_keys.size(); ++i)
			{
				(macs.get())[i].update(reinterpret_cast<uint8_t *>(&imageHeader), sizeof(imageHeader));
			}
		}
		
		// update SHA-1
		hash.Update(reinterpret_cast<uint8_t *>(&imageHeader), sizeof(imageHeader));
	}
	
	// write plaintext section table
	{
		section_iterator_t it = beginSection();
		for (; it != endSection(); ++it)
		{
			Section * section = *it;
			
			// write header for this section
			assert(sizeOfPaddingForCipherBlocks(sizeof(section_header_t)) == 0);
			section_header_t sectionHeader;
			section->fillSectionHeader(sectionHeader);
			stream.write(reinterpret_cast<char *>(&sectionHeader), sizeof(sectionHeader));
			fileBlocksWritten += numberOfCipherBlocks(sizeof(sectionHeader));
			
			// update CBC-MAC over this entry
			if (isEncrypted())
			{
				for (i=0; i < m_keys.size(); ++i)
				{
					(macs.get())[i].update(reinterpret_cast<uint8_t *>(&sectionHeader), sizeof(sectionHeader));
				}
			}
			
			// update SHA-1
			hash.Update(reinterpret_cast<uint8_t *>(&sectionHeader), sizeof(sectionHeader));
		}
	}
	
	// finished with the CBC-MAC
	if (isEncrypted())
	{
		for (i=0; i < m_keys.size(); ++i)
		{
			(macs.get())[i].finalize();
		}
	}
	
	// write key dictionary
	if (isEncrypted())
	{
		key_iterator_t it = beginKeys();
		for (i=0; it != endKeys(); ++it, ++i)
		{
			// write CBC-MAC result for this key, then update SHA-1
			RijndaelCBCMAC & mac = (macs.get())[i];
			const RijndaelCBCMAC::block_t & macResult = mac.getMAC();
			stream.write(reinterpret_cast<const char *>(&macResult), sizeof(RijndaelCBCMAC::block_t));
			hash.Update(reinterpret_cast<const uint8_t *>(&macResult), sizeof(RijndaelCBCMAC::block_t));
			fileBlocksWritten++;
			
			// encrypt DEK with this key, write it out, and update image digest
			Rijndael cipher;
			cipher.init(Rijndael::CBC, Rijndael::Encrypt, *it, Rijndael::Key16Bytes, imageHeader.m_iv);
			AESKey<128>::key_t wrappedSessionKey;
			cipher.blockEncrypt(m_sessionKey, sizeof(AESKey<128>::key_t) * 8, wrappedSessionKey);
			stream.write(reinterpret_cast<char *>(&wrappedSessionKey), sizeof(wrappedSessionKey));
			hash.Update(reinterpret_cast<uint8_t *>(&wrappedSessionKey), sizeof(wrappedSessionKey));
			fileBlocksWritten++;
		}
	}
	
	// write sections and boot tags
	{
		section_iterator_t it = beginSection();
		for (; it != endSection(); ++it)
		{
			section_iterator_t itCopy = it;
			bool isLastSection = (++itCopy == endSection());
			
			Section * section = *it;
			cipher_block_t block;
			unsigned blockCount = section->getBlockCount();
			unsigned blocksWritten = 0;
			
			Rijndael cipher;
			cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, imageHeader.m_iv);
			
			// Compute the number of padding blocks needed to align the section. This first
			// call to getPadBlockCountForOffset() passes an offset that excludes
			// the boot tag for this section.
			unsigned paddingBlocks = getPadBlockCountForSection(section, fileBlocksWritten);
			
			// Insert nop commands as padding to align the start of the section, if
			// the section has special alignment requirements.
			NopCommand nop;
			while (paddingBlocks--)
			{
				blockCount = nop.getBlockCount();
				blocksWritten = 0;
				while (blocksWritten < blockCount)
				{
					nop.getBlocks(blocksWritten, 1, &block);
					
					if (isEncrypted())
					{
						// re-init after encrypt to update IV
						cipher.blockEncrypt(block, sizeof(cipher_block_t) * 8, block);
						cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, block);
					}
					
					stream.write(reinterpret_cast<char *>(&block), sizeof(cipher_block_t));
					hash.Update(reinterpret_cast<uint8_t *>(&block), sizeof(cipher_block_t));
					
					blocksWritten++;
					fileBlocksWritten++;
				}
			}
			
			// reinit cipher for boot tag
			cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, imageHeader.m_iv);
			
			// write boot tag
			TagCommand tag(*section);
			tag.setLast(isLastSection);
			if (!isLastSection)
			{
				// If this isn't the last section, the tag needs to include any
				// padding for the next section in its length, otherwise the ROM
				// won't be able to find the next section's boot tag.
				unsigned nextSectionOffset = fileBlocksWritten + section->getBlockCount() + 1;
				tag.setSectionLength(section->getBlockCount() + getPadBlockCountForSection(*itCopy, nextSectionOffset));
			}
			blockCount = tag.getBlockCount();
			blocksWritten = 0;
			while (blocksWritten < blockCount)
			{
				tag.getBlocks(blocksWritten, 1, &block);
				
				if (isEncrypted())
				{
					// re-init after encrypt to update IV
					cipher.blockEncrypt(block, sizeof(cipher_block_t) * 8, block);
					cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, block);
				}
				
				stream.write(reinterpret_cast<char *>(&block), sizeof(cipher_block_t));
				hash.Update(reinterpret_cast<uint8_t *>(&block), sizeof(cipher_block_t));
				
				blocksWritten++;
				fileBlocksWritten++;
			}
			
			// reinit cipher for section data
			cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, imageHeader.m_iv);
			
			// write section data
			blockCount = section->getBlockCount();
			blocksWritten = 0;
			while (blocksWritten < blockCount)
			{
				section->getBlocks(blocksWritten, 1, &block);
				
				// Only encrypt the section contents if the entire boot image is encrypted
				// and the section doesn't have the "leave unencrypted" flag set. Even if the
				// section is unencrypted the boot tag will remain encrypted.
				if (isEncrypted() && !section->getLeaveUnencrypted())
				{
					// re-init after encrypt to update IV
					cipher.blockEncrypt(block, sizeof(cipher_block_t) * 8, block);
					cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, block);
				}
				
				stream.write(reinterpret_cast<char *>(&block), sizeof(cipher_block_t));
				hash.Update(reinterpret_cast<uint8_t *>(&block), sizeof(cipher_block_t));
				
				blocksWritten++;
				fileBlocksWritten++;
			}
		}
	}
	
	// write SHA-1 digest over entire image
	{
		// allocate enough room for digest and bytes to pad out to the next cipher block
		const unsigned padBytes = sizeOfPaddingForCipherBlocks(sizeof(sha1_digest_t));
		unsigned digestBlocksSize = sizeof(sha1_digest_t) + padBytes;
		smart_array_ptr<uint8_t> digestBlocks = new uint8_t[digestBlocksSize];
		hash.Final();
		hash.GetHash(digestBlocks.get());
		
		// set the pad bytes to random values
		RandomNumberGenerator rng;
		rng.generateBlock(&(digestBlocks.get())[sizeof(sha1_digest_t)], padBytes);
		
		// encrypt with session key
		if (isEncrypted())
		{
			Rijndael cipher;
			cipher.init(Rijndael::CBC, Rijndael::Encrypt, m_sessionKey, Rijndael::Key16Bytes, imageHeader.m_iv);
			cipher.blockEncrypt(digestBlocks.get(), digestBlocksSize * 8, digestBlocks.get());
		}
		
		// write to the stream
		stream.write(reinterpret_cast<char *>(digestBlocks.get()), digestBlocksSize);
	}
}
Exemple #11
0
bool App::openTree(const QString &file)
{
    NotesFileParser handler;

    connect(&handler, SIGNAL(backupLoaded(bool, const QString &)),
            this,       SLOT(setBackupLocation(bool, const QString &)));
    connect(&handler, SIGNAL(notesShowReminderAtStartUpLoaded(bool)),
            this,       SLOT(setNotesShowReminderAtStartUp(bool)));
//  connect(&handler, SIGNAL(notesWordWrapLoaded(bool)),
//          this,       SLOT(setNotesWordWrap(bool)));
//  connect(&handler, SIGNAL(notesRootNodeDecorationLoaded(bool)),
//          this,       SLOT(setNotesRootNodeDecoration(bool)));
//  connect(&handler, SIGNAL(notesShowScrollBarsLoaded(bool)),
//          this,       SLOT(setNotesShowScrollBars(bool)));
    connect(&handler, SIGNAL(entryLoaded(Entry *)),
            this,       SLOT(addEntry(Entry *)));
    connect(&handler, SIGNAL(noteLoaded(const QString &, QList<QString> *,
                                        const QString &, const QString &,
                                        int, QDateTime, const QString &, QDateTime)),
            notes,      SLOT(addNote(const QString &, QList<QString> *,
                                        const QString &, const QString &,
                                        int, QDateTime, const QString &, QDateTime)));
    connect(&handler, SIGNAL(securityPasswdLoaded(const QString &)),
            this,       SLOT(setSecurityPasswd(const QString &)));
    connect(&handler, SIGNAL(noteLoaded(const QString &, Strokes *,
                                        const QString &, const QString &,
                                        int, QDateTime, const QString &, QDateTime)),
            notes,      SLOT(addNote(const QString &, Strokes *,
                                        const QString &, const QString &,
                                        int, QDateTime, const QString &, QDateTime)));
    connect(&handler, SIGNAL(noNoteChild()),
            notes,      SLOT(noNoteChild()));

    QFile xmlFile(Global::applicationFileName("iqnotes", file + ".xml")),
    xmlRijndaelFile(Global::applicationFileName("iqnotes", file + ".rijn"));
    QXmlInputSource *source;

    // Init xml file
    if (!xmlFile.exists() && !xmlRijndaelFile.exists())
    {
        xmlFile.open(IO_WriteOnly);
        QTextStream ts(&xmlFile);

        ts << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<iqnotes>\n<entries>\n"

        << "<entry name=\"Company\">\n"
        << "<property name=\"Name\" type=\"oneLine\"/>\n"
        << "<property name=\"Address\" type=\"multiLine\"/>\n"
        << "<property name=\"Tels\" type=\"oneLine\"/>\n"
        << "<property name=\"Emails\" type=\"oneLine\"/>\n"
        << "<property name=\"Note\" type=\"multiLine\"/>\n"
        << "</entry>\n"

        << "<entry name=\"Person\">\n"
        << "<property name=\"Name\" type=\"oneLine\"/>\n"
        << "<property name=\"Nick\" type=\"oneLine\"/>\n"
        << "<property name=\"Work Address\" type=\"multiLine\"/>\n"
        << "<property name=\"Work Tel\" type=\"oneLine\"/>\n"
        << "<property name=\"Work Emails\" type=\"oneLine\"/>\n"
        << "<property name=\"Home Address\" type=\"multiLine\"/>\n"
        << "<property name=\"Home Tel\" type=\"oneLine\"/>\n"
        << "<property name=\"Emails\" type=\"oneLine\"/>\n"
        << "<property name=\"Note\" type=\"multiLine\"/>\n"
        << "</entry>\n"

        << "<entry name=\"User account\">\n"
        << "<property name=\"Host\" type=\"oneLine\"/>\n"
        << "<property name=\"Username\" type=\"oneLine\"/>\n"
        << "<property name=\"Password\" type=\"oneLine\"/>\n"
        << "<property name=\"Type\" type=\"oneLine\"/>\n"
        << "<property name=\"Note\" type=\"mutliLine\"/>\n"
        << "</entry>\n"

        << "<entry name=\"Credit card\">\n"
        << "<property name=\"Card type\" type=\"oneLine\"/>\n"
        << "<property name=\"Account #\" type=\"oneLine\"/>\n"
        << "<property name=\"Expire\" type=\"oneLine\"/>\n"
        << "<property name=\"PIN\" type=\"oneLine\"/>\n"
        << "<property name=\"Note\" type=\"mutliLine\"/>\n"
        << "</entry>\n"

        << "<entry name=\"WWW Link\">\n"
        << "<property name=\"Title\" type=\"oneLine\"/>\n"
        << "<property name=\"URL\" type=\"oneLine\"/>\n"
        << "<property name=\"Description\" type=\"multiLine\"/>\n"
        << "</entry>\n"

        << "</entries>\n"
        << "<notes>\n</notes>\n</iqnotes>\n";

        xmlFile.close();
        source = new QXmlInputSource(xmlFile);
    }
    else if (xmlRijndaelFile.exists())
    {
        StartUpPasswdBase passwdD(this, 0, true);
        passwdD.adjustSize();
        if (!passwdD.exec())
        {
            return false;
        }
        
        preferences.setPasswd(passwdD.Passwd->text());

        xmlRijndaelFile.open(IO_ReadOnly);
        uint fileSize = xmlRijndaelFile.size();
        unsigned char *rijnData = (unsigned char *) malloc(fileSize),
            *rijnDataDecrypted = (unsigned char *) malloc(fileSize);
        Rijndael rijndael;

        xmlRijndaelFile.readBlock((char *)rijnData, fileSize);
        rijndael.init(Rijndael::CBC, Rijndael::Decrypt, preferences.passwd16Bin, Rijndael::Key16Bytes);
        rijndael.padDecrypt(rijnData, fileSize, rijnDataDecrypted);

		// yeah, stupid
        if (memcmp((void *)"<iqnotes>", (void *)rijnDataDecrypted, 9) != 0 && memcmp((void *)"<?xml version", (void *)rijnDataDecrypted, 13) != 0)
        {
            free(rijnData);
            free(rijnDataDecrypted);

            QMessageBox::critical(this, "Bad password", "Please,\ntype correct password.");

            return false;
        }

        source = new QXmlInputSource();
        //        source->setData(QString((char *)rijnDataDecrypted));
        source->setData(QString::fromUtf8((char *)rijnDataDecrypted));

        free(rijnData);
        free(rijnDataDecrypted);
    }
    else
    {
        source = new QXmlInputSource(xmlFile);
    }

    QXmlSimpleReader reader;
    reader.setContentHandler(&handler);
    reader.setErrorHandler(new NotesFileParserError);
    if(!reader.parse(*source))
        qWarning(tr("parse error"));

    delete source;

    setCaption("IQNotes :: " + file);
     
    return true;
}
Exemple #12
0
bool App::saveTree()
{
    // backup dir checking (see also preferences.cpp)
    if (preferences.saveBackupFile)
    {
        QDir backupDir(preferences.backupLocation);
        
        if (!backupDir.exists())
        {
            QMessageBox::critical(this, "Invalid directory", "Please, enter the existing\ndirectory in backup location.", 0, 0);
            return false;
        }
    }
    
    QFile saveF(Global::applicationFileName("iqnotes", currentFile + ".xml"));
    QFile rijnF(Global::applicationFileName("iqnotes", currentFile + ".rijn"));

    QString saveS;
    QTextStream saveData(saveS, IO_WriteOnly);
	saveData.setEncoding(saveData.UnicodeUTF8);
	
    saveData << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<iqnotes>\n"
    << "<config>\n"
    << "<backup save=\"" << (preferences.saveBackupFile ? "yes" : "no") << "\" location=\"" << preferences.backupLocation << "\"/>\n"
             << "<notes showreminder=\"" << (preferences.showReminder ? "yes" : "no") << "\" />\n"
    << "<security passwd=\"" << preferences.passwdHex << "\"/>\n"
    << "</config>\n"

    << "<entries>\n";

    for (Entry *e = entriesList->first(); e; e = entriesList->next())
    {
        saveData << "<entry name=\"" << quoteXML(e->getName()) << "\" defaultpic=\"" << quoteXML(e->getDefaultPic()) << "\">\n";

        for (PropertyStruct *ps = e->first(); ps; ps = e->next())
        {
            saveData << "<property name=\"" << quoteXML(ps->getName()) << "\" "
            << "type=\"" << (ps->getType() == PropertyStruct::ONE_LINE ? "oneLine" : "multiLine") << "\"/>\n";
        }

        saveData << "</entry>\n";
    }

    saveData << "</entries>\n";

    notes->saveTree(&saveData);

    saveData << "</iqnotes>\n";
	//SF.close();
    QCString dataUTF8 = saveS.utf8();

    if (!preferences.passwdHex.length())
    {
        saveF.open(IO_WriteOnly);

        QTextStream saveData1(&saveF);
		saveData1.setEncoding(saveData1.UnicodeUTF8);
		saveData1 << saveS;

        if (preferences.saveBackupFile)
        {
            QFile backupSaveF(preferences.backupLocation + "/" + currentFile + ".xml");
            QTextStream saveData2(&backupSaveF);
            backupSaveF.open(IO_WriteOnly);
            saveData2 << dataUTF8;
        }

        if (rijnF.exists())
            rijnF.remove();
    }
    else
    {
        Rijndael rijndael;
        unsigned char *rijnEncrypt = (unsigned char*)malloc(dataUTF8.length() + 16);

        rijnF.open(IO_WriteOnly);

        rijndael.init(Rijndael::CBC, Rijndael::Encrypt, preferences.passwd16Bin, Rijndael::Key16Bytes);
        int len = rijndael.padEncrypt((unsigned char*)(const char*)dataUTF8, dataUTF8.length(), rijnEncrypt);

        rijnF.writeBlock((const char *)rijnEncrypt, len);
        if (preferences.saveBackupFile)
        {
            QFile rijnBackupF(preferences.backupLocation + "/" + currentFile + ".rijn");
            rijnBackupF.open(IO_WriteOnly);
            rijnBackupF.writeBlock((const char *)rijnEncrypt, len);
        }

        free(rijnEncrypt);

        if (saveF.exists())
            saveF.remove();
    }

    return true;
}