Пример #1
0
int encfile(aes *ctx, byte *encoutbuf)
{
   fpos_t          flen;
   unsigned long   i=0, l=0, j, k;

   fillrand(encoutbuf, 16);           /* set an IV for CBC mode           */
   FLEN = 4096;
   fillrand(inbuf, 1);             /* make top 4 bits of a byte random */
   l = 15;                         /* and store the length of the last */
   /* block in the lower 4 bits        */
   inbuf[0] = ((char)FLEN & 15) | (inbuf[0] & ~15);

   for(j = 0; j <256; j++)
   {                               /* input 1st 16 bytes to buf[1..16] */
      for(k = 0; k < 16; ++k)
         inbuf[k] = jrand();

      for(i = 0; i < 16; ++i)         /* xor in previous cipher text  */
         inbuf[i] ^= encoutbuf[i];

      encrypt(inbuf, encoutbuf, ctx);    /* and do the encryption        */
      /* in all but first round read 16   */
      l = 16;                     /* bytes into the buffer            */
   }

   return 0;
}
Пример #2
0
int main()
{
  std::uniform_real_distribution<Real> dist(0, 1);
  auto rand = [&dist] { return dist(rng); };

  Vec<Real> theta{ 26 };
  size_t n_bones = 15;
  size_t n_verts = 500;

  fillrand(&theta, std::uniform_real_distribution<Real>(-1, 1));

  Mat<Real, 3, N_VERTS> base_positions{ 3, n_verts };
  for (int i = 0; i < n_verts; ++i)
    fillrand(&base_positions[i], std::uniform_real_distribution<Real>(1, 10));

  std::vector<Real4x4> base_relatives{ n_bones };
  for (int i = 0; i < n_bones; ++i) {
    Vec<Real, 3> rvec; fillrand(&rvec, std::uniform_real_distribution<Real>(-2, 2));
    Vec<Real, 3> tvec; fillrand(&tvec, std::uniform_real_distribution<Real>(1, 2));
    base_relatives[i] = Rt_to_transform(angle_axis_to_rotation_matrix(rvec), tvec);
  }
    
  std::vector<int> parents{ 
    -1,  0,  1, 
    -1,  3,  4,
    -1,  6,  7,
    -1,  9, 10,
    -1, 12, 13,
    };

  Mat<Real, N_VERTS, N_BONES> weights{ n_verts, n_bones };
  for (int i = 0; i < n_verts; ++i) 
    for (int j = 0; j < n_bones; ++j) {
      if (rand() < 4.0 / n_bones)
        weights[j][i] = rand();
    }


  boost::timer::auto_cpu_timer t;

  // Debug 150s 
  // Release 1s
  double total = 0;
  size_t N = 1000;
#ifdef _DEBUG
  N = N / 10;  // Debug is roughly this much slower than release -- multiply timings.
#endif
  for (size_t count = 0; count < N; ++count) {
    std::vector<Vec3<Real>> pose_params = to_pose_params(theta, n_bones);
      
    Mat<Real, 3, N_VERTS> verts = get_skinned_vertex_positions(base_relatives, parents, base_positions, weights, pose_params);

    total += sumsq(verts[1]);
  }

  std::cout << "total =" << total << ", time per call = " << t.elapsed().wall / double(N) / 1e6 << "ms" << std::endl;

  return 0;
}
Пример #3
0
ATCResult ATCLocker_impl::writeEncryptedHeader(ostream *dst)
{
	stringstream whole_header;
	generateEncryptedHeader(&whole_header);

	//暗号化部分のヘッダデータサイズを計算
	const int32_t block_length = (whole_header.str().size() + ATC_BUF_SIZE - 1) / ATC_BUF_SIZE;
	const int32_t encrypt_header_size = block_length * ATC_BUF_SIZE;

	dst->write(reinterpret_cast<const char*>(&encrypt_header_size), sizeof(int32_t));

	//初期化ベクトル(IV)を生成
	fillrand(chain_buffer_, ATC_BUF_SIZE);
	dst->write(chain_buffer_, ATC_BUF_SIZE);

	char buffer[ATC_BUF_SIZE] = {0};

	while (whole_header.read(buffer, ATC_BUF_SIZE).gcount() != 0)
	{
		encryptBuffer(buffer, chain_buffer_);

		dst->write(buffer, ATC_BUF_SIZE);
		for (int i = 0; i < ATC_BUF_SIZE; i++)
		{
			buffer[i] = 0;
		}
	}

	//初期化ベクトル(IV)を生成
	fillrand(chain_buffer_, ATC_BUF_SIZE);
	dst->write(chain_buffer_, ATC_BUF_SIZE);

	if (!initZlib())
	{
        return ATC_ERR_ZLIB_ERROR;
    }

	return ATC_OK;
}
Пример #4
0
 void
 test_Validators()
 {
     int const N (5);
     testcase ("Validators");
     typedef hardened_hash_map <int, Validator> Validators;
     Validators vv;
     for (int i = 0; i < N; ++i)
         vv.emplace (i, Validator{});
     std::random_device rng;
     std::mt19937_64 gen {rng()};
     std::array <std::uint8_t, RippleLedgerHash::size> buf;
     fillrand (buf.data(), buf.size(), gen);
     for (int i = 0; i < 100000; ++i)
     {
         // maybe change the ledger hash
         if ((gen() % 20) == 0)
             fillrand (buf.data(), buf.size(), gen);
         RippleLedgerHash h (buf.data(), buf.data() + buf.size());
         // choose random validator
         Validator& v (vv[gen() % vv.size()]);
         // choose random operation
         //int const choice = gen() % 2;
         int const choice = 1;
         switch (choice)
         {
         case 0:
             v.on_ledger(h);
             break;
         case 1:
             v.on_validation(h);
             break;
         };
     }
     pass();
 }
Пример #5
0
 void
 test_aged_insert()
 {
     testcase ("aged insert");
     std::random_device rng;
     std::mt19937_64 gen {rng()};
     Table table (get_seconds_clock());
     for (int i = 0; i < 10000; ++i)
     {
         std::array <std::uint8_t, RippleLedgerHash::size> buf;
         fillrand (buf.data(), buf.size(), gen);
         RippleLedgerHash h (buf.data(), buf.data() + buf.size());
         table.insert (std::make_pair (h, Entry()));
     }
     pass();
 }
Пример #6
0
int decfile(aes *ctx, byte *decoutbuf)
{
   int     i,j, l, flen, k;

   fillrand(inbuf1, 16);           /* set an IV for CBC mode           */

   for(k = 0; k < 16; ++k)
      inbuf2[k] = jrand();
   
   decrypt(inbuf2, decoutbuf, ctx);   /* decrypt it                       */

   for(i = 0; i < 16; ++i)         /* xor with previous input          */
      decoutbuf[i] ^= inbuf1[i];

   flen = 0;  /* recover length of the last block and set */
   l = 15;                 /* the count of valid bytes in block to 15  */
   bp1 = inbuf1;           /* set up pointers to two input buffers     */
   bp2 = inbuf2;

   for(j = 0; j < 256; ++j)
   {
      for(k = 0; k < 16; ++k)
         bp1[k] = jrand();

      decrypt(bp1, decoutbuf, ctx);  /* decrypt the new input block and  */

      for(i = 0; i < 16; ++i)     /* xor it with previous input block */
         decoutbuf[i] ^= bp2[i];

      /* set byte count to 16 and swap buffer pointers                */

      l = i; tp = bp1, bp1 = bp2, bp2 = tp;
   }

   return 0;
}
Пример #7
0
/* Generate a temporary file name based on TMPL.  TMPL must match the
   rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
   does not exist at the time of the call to __gen_tempname.  TMPL is
   overwritten with the result.

   KIND may be one of:
   __GT_NOCREATE:       simply verify that the name does not exist
                        at the time of the call.
   __GT_FILE:           create the file using open(O_CREAT|O_EXCL)
                        and return a read-write fd.  The file is mode 0600.
   __GT_BIGFILE:        same as __GT_FILE but use open64().
   __GT_DIR:            create a directory, which will be mode 0700.

*/
int attribute_hidden __gen_tempname (char *tmpl, int kind)
{
    char *XXXXXX;
    unsigned int i;
    int fd, save_errno = errno;
    unsigned char randomness[6];
    size_t len;

    len = strlen (tmpl);
    /* This is where the Xs start.  */
    XXXXXX = tmpl + len - 6;
    if (len < 6 || strcmp (XXXXXX, "XXXXXX"))
    {
	__set_errno (EINVAL);
	return -1;
    }

    for (i = 0; i < TMP_MAX; ++i) {
	int j;
	/* Get some random data.  */
	if (fillrand(randomness, sizeof(randomness)) != sizeof(randomness)) {
	    /* if random device nodes failed us, lets use the braindamaged ver */
	    brain_damaged_fillrand(randomness, sizeof(randomness));
	}
	for (j = 0; j < sizeof(randomness); ++j)
	    XXXXXX[j] = letters[randomness[j] % NUM_LETTERS];

	switch (kind) {
	    case __GT_NOCREATE:
		{
		    struct stat st;
		    if (stat (tmpl, &st) < 0) {
			if (errno == ENOENT) {
			    fd = 0;
			    goto restore_and_ret;
			} else
			    /* Give up now. */
			    return -1;
		    } else
			fd = 0;
		}
	    case __GT_FILE:
		fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
		break;
#if defined __UCLIBC_HAS_LFS__
	    case __GT_BIGFILE:
		fd = open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
		break;
#endif
	    case __GT_DIR:
		fd = mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
		break;
	    default:
		fd = -1;
		assert (! "invalid KIND in __gen_tempname");
	}

	if (fd >= 0) {
restore_and_ret:
	    __set_errno (save_errno);
	    return fd;
	}
	else if (errno != EEXIST)
	    /* Any other error will apply also to other names we might
	       try, and there are 2^32 or so of them, so give up now. */
	    return -1;
    }

    /* We got out of the loop because we ran out of combinations to try.  */
    __set_errno (EEXIST);
    return -1;
}
Пример #8
0
int encfile(FILE *fin, FILE *fout, aes_encrypt_ctx ctx[1], const char* ifn, const char* ofn)
{   char            dbuf[3 * BLOCK_LEN];
    unsigned long   i, len, wlen = BLOCK_LEN;

    // When ciphertext stealing is used, we three ciphertext blocks so
    // we use a buffer that is three times the block length.  The buffer
    // pointers b1, b2 and b3 point to the buffer positions of three
    // ciphertext blocks, b3 being the most recent and b1 being the
    // oldest. We start with the IV in b1 and the block to be decrypted
    // in b2.

    // set a random IV

    fillrand(dbuf, BLOCK_LEN);

    // read the first file block
    len = (unsigned long) fread(dbuf + BLOCK_LEN, 1, BLOCK_LEN, fin);

    if(len < BLOCK_LEN)
    {   // if the file length is less than one block

        // xor the file bytes with the IV bytes
        for(i = 0; i < len; ++i)
            dbuf[i + BLOCK_LEN] ^= dbuf[i];

        // encrypt the top 16 bytes of the buffer
        aes_encrypt(dbuf + len, dbuf + len, ctx);

        len += BLOCK_LEN;
        // write the IV and the encrypted file bytes
        if(fwrite(dbuf, 1, len, fout) != len)
            return WRITE_ERROR;

        return OK;
    }
    else    // if the file length is more 16 bytes
    {   char    *b1 = dbuf, *b2 = b1 + BLOCK_LEN, *b3 = b2 + BLOCK_LEN, *bt;

        // write the IV
        if(fwrite(dbuf, 1, BLOCK_LEN, fout) != BLOCK_LEN)
            return WRITE_ERROR;

        for( ; ; )
        {
            // read the next block to see if ciphertext stealing is needed
            len = (unsigned long)fread(b3, 1, BLOCK_LEN, fin);

            // do CBC chaining prior to encryption for current block (in b2)
            for(i = 0; i < BLOCK_LEN; ++i)
                b1[i] ^= b2[i];

            // encrypt the block (now in b1)
            aes_encrypt(b1, b1, ctx);

            if(len != 0 && len != BLOCK_LEN)    // use ciphertext stealing
            {
                // set the length of the last block
                wlen = len;

                // xor ciphertext into last block
                for(i = 0; i < len; ++i)
                    b3[i] ^= b1[i];

                // move 'stolen' ciphertext into last block
                for(i = len; i < BLOCK_LEN; ++i)
                    b3[i] = b1[i];

                // encrypt this block
                aes_encrypt(b3, b3, ctx);

                // and write it as the second to last encrypted block
                if(fwrite(b3, 1, BLOCK_LEN, fout) != BLOCK_LEN)
                    return WRITE_ERROR;
            }

            // write the encrypted block
            if(fwrite(b1, 1, wlen, fout) != wlen)
                return WRITE_ERROR;

            if(len != BLOCK_LEN)
                return OK;

            // advance the buffer pointers
            bt = b3, b3 = b2, b2 = b1, b1 = bt;
        }
    }
}
//===========================================================================
// ヘッダ情報を生成する
//===========================================================================
bool __fastcall TAttacheCaseFileEncrypt::CreateHeaderData
	(TMemoryStream *pms, TStringList *FileList, TStringList *FilePathList, __int64 &AllTotalFileSize)
{

int i, c;

int ret;
int Index = 0;
int HeaderSizeAddress = 0;
TSearchRec sr;
String OneLine;
String DirPath, FileName;

String MsgText;

//暗号部トークン
const AnsiString Passcode_AttacheCase = "Passcode:AttacheCase\n";
//暗号化ファイルの作成日
AnsiString LastDateTimeString = "LastDateTime:" + DateTimeToStr(Now()) + "\n";

//旧ヘッダーテキストすべて
AnsiString Fn_HeaderText;
//Unicode用ヘッダーテキストすべて
String U_HeaderText;

int EncryptHeaderSize = 0;  //暗号部ヘッダサイズ

char buffer[BUF_SIZE];
char chain_buffer[BUF_SIZE];

TStringList *HeaderDataList;
TMemoryStream* tpms;          //テンポラリメモリストリーム

//-----------------------------------
// ヘッダ情報(平文)
//-----------------------------------
const char charReservedValue[4] = { 0, 0, 0, 0 };

const char charDataSubVersion = ATC_DATA_SUB_VERSION;
const char charOptMissTypeLimitsNumOption = intOptMissTypeLimitsNumOption;
const char charOptBrokenFileOption = (fOptBrokenFileOption > 0 ? 1 : 0);
const char charTokenString[17] = "_AttacheCaseData";
const int DataFileVersion = ATC_DATA_FILE_VERSION;
const int AlgorismType = TYPE_ALGORISM_RIJNDAEL;

//データサブバージョン                              : 1byte
pms->Write(&charDataSubVersion, sizeof(char));
//予約データ(reserved)                             : 1byte
pms->Write(&charReservedValue, sizeof(char));
//ミスタイプ回数                                    : 1byte
pms->Write(&charOptMissTypeLimitsNumOption, sizeof(char));
//破壊するか否か                                    : 1byte
pms->Write(&charOptBrokenFileOption, sizeof(char));
//トークン                                          : 16byte
pms->Write(&charTokenString, 16);
//データファイルバージョン                          : 4byte
pms->Write(&DataFileVersion, sizeof(int));
//アルゴリズムタイプ                                : 4byte
pms->Write(&AlgorismType, sizeof(int));
//暗号化部分のヘッダデータサイズ(先に確保しておく):4byte
HeaderSizeAddress = pms->Position;
pms->Write(&EncryptHeaderSize, sizeof(int));

//-----------------------------------
// ヘッダ情報(暗号化部分)
//-----------------------------------

//進捗状況表示
ProgressPercentNum = -1;
//'暗号化するファイルリストの生成中...'
ProgressStatusText = LoadResourceString(&Msgencrypt::_LABEL_STATUS_TITLE_LISTING);

//ヘッダデータリスト(文字列)
HeaderDataList = new TStringList;
//パスワード
HeaderDataList->Add(Passcode_AttacheCase);
//作成日
HeaderDataList->Add(LastDateTimeString);

for ( i = 0; i < FileList->Count; i++ ){
	//ファイル
	if (FileExists(FileList->Strings[i]) == true) {
		DirPath = ExtractFileDir(FileList->Strings[i]);
		FileName = ExtractFileName(FileList->Strings[i]);
		ProgressMsgText = FileName;      //処理中のファイル名
		AllTotalFileSize +=
			GetFileInfoList(Index, DirPath, FileName, FileList->Strings[i], FilePathList, HeaderDataList);
	}
	//ディレクトリ
	else{
		DirPath = ExtractFileDir(FileList->Strings[i]);
		FileName = ExtractFileName(FileList->Strings[i]);
		ProgressMsgText = FileName;      //処理中のファイル名
		//トップディレクトリ
		GetFileInfoList(Index, DirPath, FileName, FileList->Strings[i], FilePathList, HeaderDataList);
		//その配下
		AllTotalFileSize +=
			GetFileInfoList(Index, FileList->Strings[i], "", FileList->Strings[i], FilePathList, HeaderDataList);
	}

	//ユーザーキャンセル
	if (Terminated == true) {
		delete HeaderDataList;
		return(false);
	}

}// end for;

//進捗状況表示
ProgressPercentNum = -1;
//'ヘッダデータを書き込んでいます...'
ProgressStatusText = LoadResourceString(&Msgencrypt::_LABEL_STATUS_TITLE_ENCRYPTING_LIST);
ProgressMsgText = "";

//メモリストリームへ書き込み
tpms = new TMemoryStream;

//------------------------------------------------
// 暗号化時にヘッダデータの互換性維持
//---------------------------------------------------
HeaderDataList->SaveToStream(tpms, TEncoding::GetEncoding(932));
//新バージョン(ver.2.8.0~)用(UTF-8)に保存
for (i = 0; i < HeaderDataList->Count; i++) {
	HeaderDataList->Strings[i] = StringReplace(HeaderDataList->Strings[i],"Fn_","U_",TReplaceFlags()<<rfIgnoreCase );
}
HeaderDataList->SaveToStream(tpms, TEncoding::UTF8);

delete HeaderDataList;

//-----------------------------------
//ヘッダ情報の暗号化
//-----------------------------------

//暗号化の準備
gentables();
//キー入力
gkey( 8, 8, key);

for (i = 0; i < BUF_SIZE; i++) {
	buffer[i] = 0;
}

//初期化ベクトル(IV)を生成
fillrand(chain_buffer, BUF_SIZE);
pms->Write(chain_buffer, BUF_SIZE);

//先頭にポインタを戻す
tpms->Seek((__int64)0, TSeekOrigin::soBeginning);
EncryptHeaderSize = 0;

//CBCモードで書き込む
while (tpms->Read( buffer, BUF_SIZE ) != NULL){

	EncryptHeaderSize += BUF_SIZE;

	// xor
	for ( i = 0; i < BUF_SIZE; i++ ){
		buffer[i] ^= chain_buffer[i];
	}

	// rijndael
	rijndael_encrypt(buffer);

	pms->Write(buffer, BUF_SIZE);

	//CBC&バッファの初期化
	for ( i = 0; i < BUF_SIZE; i++ ){
		chain_buffer[i] = buffer[i];
		buffer[i] = 0;
	}

	//ユーザーキャンセル
	if (Terminated == true) {
		delete tpms;
		return(false);
	}

}//loop;

delete tpms;

//暗号化部分のヘッダデータサイズ(確保しておいた場所へ改めて書き込む)
pms->Position = HeaderSizeAddress;
pms->Write(&EncryptHeaderSize, sizeof(int));
//先頭にポインタを戻す
pms->Seek((__int64)0, TSeekOrigin::soBeginning);

return(true);


}//end CreateHeaderData;
//===========================================================================
// スレッド実行
//===========================================================================
void __fastcall TAttacheCaseFileEncrypt::Execute()
{

int i, c;
int res;

float ProgressPercentNumF;  //進捗パーセンテージ(浮動小数点)

z_stream z;                 // zlibライブラリとやりとりするための構造体
int flush, status;          // zlib

//出力する暗号化ファイルのタイムスタンプを元ファイルに合わせる
HANDLE hFile;
//_WIN32_FIND_DATAW first_fd;
ZeroMemory(&first_fd, sizeof(_WIN32_FIND_DATAW));

int len, pos;
int FileIndex;
String FilePath;

int HeaderSize;                          //ヘッダデータサイズ
__int64 CurrentDriveFreeSpaceSize = -1;  //保存するドライブの空き容量

//実行可能形式出力ファイルのデータサイズ
__int64 ExeAllSize = 0;
__int64 ExeSize    = 0;

//全体のファイルサイズ
AllTotalSize = 0;
__int64 TotalSize = 0;

//バッファ
char source_buffer[BUF_SIZE];
char read_buffer[BUF_SIZE];
char out_buffer[BUF_SIZE];
char chain_buffer[BUF_SIZE]; // IVなどを格納するチェインバッファ
char margin_buffer[BUF_SIZE];

//ファイルストリーム
TFileStream *fsIn;
TFileStream *fsOut;
TFileStream *fsExe;

//オープン中か
bool fOpenIn;
bool fOpenOut;
//メモリストリーム
TMemoryStream *pms = new TMemoryStream;

// マージンバッファサイズ
int MarginBufSize = MARGIN_BUF_SIZE;

// PKCS #7 Pading num.
unsigned char paddingNum = 0;

//---------------------------------------
// 同名ファイルがあるのでダイアログ表示
//---------------------------------------
if ( fConfirmOverwirte == true && fOverwirteYesToAll == false ) {

	if (FileExists(OutFilePath) == true) {
		//同名ファイルの上書き確認メッセージダイアログ
		MsgText = LoadResourceString(&Msgencrypt::_MSG_CONFIRM_OVER_WRITE_SAME_FILE)+"\n"+OutFilePath;
		Synchronize(&PostConfirmOverwriteMessageForm);
		if ( MsgReturnVal == mrYes ) {
			//上書きOKなのでFilePathはそのまま
		}
		else if ( MsgReturnVal == mrNo ) {
			//別名保存でFilePath文字列が書き換えられてきている
			OutFilePath = MsgReturnPath;
		}
		else if ( MsgReturnVal == mrYesToAll ) {
			//すべて上書き(YesToAll)
			fOverwirteYesToAll = true;
		}
		else if ( MsgReturnVal == mrCancel ) {
			//キャンセル
			delete pms;
			goto LabelStop;
		}
	}

}

//---------------------------------------
// ヘッダ情報の生成&ファイル総サイズ取得
//---------------------------------------

//'暗号化するファイルリストの生成中...'
ProgressStatusText = LoadResourceString(&Msgencrypt::_LABEL_STATUS_TITLE_LISTING);

if ( CreateHeaderData( pms, InputFileList, FilePathList, AllTotalSize) == false ){
	if (Terminated == true) {
		//ユーザーキャンセルで抜けてきた
		delete pms;
		goto LabelStop;
	}
	else{
		//'暗号化するファイルを開けません。他のアプリケーションが使用中の可能性があります。'
		MsgText = LoadResourceString(&Msgencrypt::_MSG_ERROR_FILE_OPEN);
		MsgType = mtError;
		MsgButtons = TMsgDlgButtons() << mbOK;
		MsgDefaultButton = mbOK;
		Synchronize(&PostConfirmMessageForm);
		delete pms;
		goto LabelError;
	}

}

//-----------------------------------
// ディスクの空き容量チェック
//-----------------------------------

CurrentDriveFreeSpaceSize = GetDiskFreeSpaceNum(OutFilePath);

if (CurrentDriveFreeSpaceSize > -1 ) {
	if ( AllTotalSize > CurrentDriveFreeSpaceSize ) {
		//"ディスクの空き容量が足りません! 暗号化ファイルを保存できません。\n
		//暗号化を中止します。;"
		MsgText = LoadResourceString(&Msgencrypt::_MSG_ERROR_NO_DISK_FREE_SPACE);
		MsgType = mtError;
		MsgButtons = TMsgDlgButtons() << mbOK;
		MsgDefaultButton = mbOK;
		Synchronize(&PostConfirmMessageForm);
		delete pms;
		goto LabelError;
	}
}
else{
	// -1はネットワークドライブの可能性があるので無視
	//(万が一、別のエラーの場合、実際書き込みに移行したときエラーが発生する)
}

//-----------------------------------
// 実行可能形式でかつ
// 合計バイト数が4GBを越えたときのエラー
//-----------------------------------
if ( fExeOutputOption == true && fOver4gbOk == false && AllTotalSize > SIZE_4GB ){

	//実行形式ファイルのサイズが4GBを超えてしまう可能性があります!\n
	//Win32アプリケーションとして実行できなくなるかもしれませんがよろしいですか?';
	MsgText = LoadResourceString(&Msgencrypt::_MSG_ERROR_OVER_4GB_EXE);
	MsgType = mtError;
	MsgButtons = TMsgDlgButtons() << mbYes << mbNo;
	MsgDefaultButton = mbNo;
	Synchronize(&PostConfirmMessageForm);

	if ( MsgReturnVal == mbNo) {
		//キャンセル
		delete pms;
		goto LabelStop;
	}

}

//-----------------------------------
// 暗号化ファイルの生成開始
//-----------------------------------
//'暗号化しています...'
ProgressStatusText = LoadResourceString(&Msgencrypt::_LABEL_STATUS_TITLE_ENCRYPTING);
ProgressMsgText = ExtractFileName(OutFilePath);

TotalSize = 0;

try{
	fsOut = new TFileStream(OutFilePath, fmCreate);
	fOpenOut = true;
}
catch(...){
	//'保存する先のファイルが開けません。他のアプリケーションが使用中の可能性があります。'
	MsgText = LoadResourceString(&Msgencrypt::_MSG_ERROR_OUT_FILE_OPEN) + "\n" + OutFilePath;
	MsgType = mtError;
	MsgButtons = TMsgDlgButtons() << mbOK;
	MsgDefaultButton = mbOK;
	Synchronize(&PostConfirmMessageForm);
	delete pms;
	goto LabelError;
}

//-----------------------------------
// 実行可能形式の出力
//-----------------------------------
if ( fExeOutputOption == true ){

	//-----------------------------------
	// 自分のお尻から実行データを抽出
	//-----------------------------------

	//自分自身の実行ファイルを開く
	try{
		fsExe = new TFileStream(Application->ExeName, fmOpenRead | fmShareDenyWrite);
	}
	catch(...){
		//'実行可能形式出力に失敗しました。暗号化処理を中止します。'
		MsgText = LoadResourceString(&Msgencrypt::_MSG_ERROR_EXEOUT_FAILED);
		MsgType = mtError;
		MsgButtons = TMsgDlgButtons() << mbOK;
		MsgDefaultButton = mbOK;
		Synchronize(&PostConfirmMessageForm);
		delete pms;
		goto LabelError;
	}

	//切り出すサイズを取得
	fsExe->Seek(-(__int64)sizeof(__int64), TSeekOrigin::soEnd);
	fsExe->Read(&ExeAllSize, sizeof(__int64));

	//処理する合計サイズに実行形式分を加える
	AllTotalSize += ExeAllSize;

	//自己実行可能形式データの境界へ
	fsExe->Seek(-(__int64)ExeAllSize-sizeof(__int64), TSeekOrigin::soEnd);

	while(fsExe->Read(read_buffer, BUF_SIZE) != 0 ){
		ExeSize+=BUF_SIZE;
		//書き込む
		if ( ExeSize < ExeAllSize ){
			fsOut->Write(read_buffer, BUF_SIZE);
			TotalSize += BUF_SIZE;
		}
		else{
			fsOut->Write(read_buffer, ExeSize-ExeAllSize);
			TotalSize += (ExeSize-ExeAllSize);
		}
		//進捗表示
		ProgressPercentNumF = (float)TotalSize/AllTotalSize;
		ProgressPercentNum = (int)(ProgressPercentNumF*100);
		if (AllTotalSize < 104857600) {	// 100MB未満
			ProgressPercentNumText = IntToStr(ProgressPercentNum)+"%";
		}
		else{
			ProgressPercentNumText = FloatToStrF(ProgressPercentNumF*100, ffNumber, 4, 1)+"%";
		}
	}
	//自分自身を閉じる
	delete fsExe;
}

//-----------------------------------
// ヘッダ情報の描き込み
//-----------------------------------

pms->SaveToStream(fsOut);	//fsOutに追記
delete pms;


//-----------------------------------
// Rijndaelの初期化
//-----------------------------------

gentables();

gkey( 8, 8, key);

// 初期化ベクトルを生成して先頭に書き込む
fillrand(chain_buffer, BUF_SIZE);

if ( fsOut->Write(chain_buffer, BUF_SIZE) < BUF_SIZE ){
	//''保存先に指定された暗号化ファイルに書き込めません。
	MsgText = LoadResourceString(&Msgencrypt::_MSG_ERROR_OUT_FILE_WRITE) + "\n" + OutFilePath;
	MsgType = mtError;
	MsgButtons = TMsgDlgButtons() << mbOK;
	MsgDefaultButton = mbOK;
	Synchronize(&PostConfirmMessageForm);
	goto LabelError;
}

//-----------------------------------
// zlib 初期化(圧縮においてすべてのメモリ管理をライブラリに任せる)
z.zalloc = Z_NULL;
z.zfree  = Z_NULL;
z.opaque = Z_NULL;
//z.next_in = Z_NULL;

// 第2引数は圧縮の度合。0~9 の範囲の整数で,0 は無圧縮
// Z_DEFAULT_COMPRESSION (= 6) が標準

if (deflateInit(&z, CompressRateNum) != Z_OK){
	//zlibエラー表示はラベル先で
	goto LabelError;
}

//出力バッファの初期化
for(i = 0; i < BUF_SIZE; i++){
	out_buffer[i] = 0;
}

// zlibに入出力バッファをセットする
z.avail_in  = 0;                    // 入力バッファ中のデータのバイト数
z.next_out  = out_buffer;           // 出力バッファ残量
z.avail_out = BUF_SIZE;             // 出力ポインタ

// 通常は deflate() の第2引数は Z_NO_FLUSH にして呼び出す
flush = Z_NO_FLUSH;

FileIndex = 0;

while(!Terminated) {

	//-----------------------------------
	//入力
	//-----------------------------------
	if ( z.avail_in == 0 && flush != Z_FINISH){

		pos = 0;

		for(i = 0; i < BUF_SIZE; i++){
			source_buffer[i] = 0;
			read_buffer[i] = 0;
		}

		while ( pos < BUF_SIZE ){

			//オープン中のファイルがあればそこから読む
			if ( fOpenIn == true ) {

				if (pos < BUF_SIZE) {

					len = fsIn->Read(read_buffer, BUF_SIZE - pos);
					TotalSize+=len;

					for (i = 0; i < len; i++) {
						source_buffer[pos+i] = read_buffer[i];
					}

					if (len < BUF_SIZE - pos) {
						fOpenIn = false; //ファイルを閉じる
						delete fsIn;
					}

				}

				pos += len;

			}
			//ファイルを開く
			else{
				if (FileIndex < FilePathList->Count) {
					while(FileIndex < FilePathList->Count){
						if (FilePathList->Strings[FileIndex] != "") {
							try{
								fsIn = new TFileStream(FilePathList->Strings[FileIndex], fmOpenRead | fmShareDenyWrite);
								fOpenIn = true;
								FileIndex++;
								break;
							}
							catch(...){
								//'暗号化するファイルを開けません。他のアプリケーションが使用中の可能性があります。'
								MsgText = LoadResourceString(&Msgencrypt::_MSG_ERROR_FILE_OPEN);
								MsgType = mtError;
								MsgButtons = TMsgDlgButtons() << mbOK;
								MsgDefaultButton = mbOK;
								Synchronize(&PostConfirmMessageForm);
								fOpenIn = false;
								goto LabelError;
							}
						}
						FileIndex++;
					}
				}
				else{

					//読み込むファイルがなくなったので、
					//お尻にダミーのマージンデータを挿入する
					//
					//【補足】
					// 本来はここにあるマージンデータ挿入処理は不要ですが、
					// 昔に作った際に復号の際に圧縮データ境界のチェックを
					// 怠っていたため、このように余分なデータを
					// 入れておくという力業を使っています(すみません...)
					fillrand(margin_buffer, BUF_SIZE);

					for (i = pos; i < BUF_SIZE; i++) {
						source_buffer[i] = margin_buffer[i];
					}

					pos = BUF_SIZE;
					MarginBufSize -= BUF_SIZE;

				}//end if (FileIndex < FilePathList->Count);

			}//end if ( fOpenIn == true );

		}//while ( pos < BUF_SIZE && 0 < MarginBufSize );

		if (MarginBufSize < 1) {
			flush = Z_FINISH;	//入力バッファはこれが最後
		}

		z.next_in = source_buffer;
		z.avail_in = pos;

	}//end if ( z.avail_in == 0 );

	//-----------------------------------
	//圧縮
	//-----------------------------------
	if ( z.avail_out > 0 ){
		status = deflate(&z, flush);
	}
	if (status == Z_STREAM_END){
			break;
	}
	if (status != Z_OK ){
		//#define Z_OK              0
		//#define Z_STREAM_END      1
		//#define Z_NEED_DICT       2
		//#define Z_ERRNO         (-1)
		//#define Z_STREAM_ERROR  (-2)
		//#define Z_DATA_ERROR    (-3)
		//#define Z_MEM_ERROR     (-4)
		//#define Z_BUF_ERROR     (-5)
		//#define Z_VERSION_ERROR (-6)
		goto LabelError;
	}
	//-----------------------------------
	//出力
	//-----------------------------------
	if ( z.avail_out == 0 ){

		// CBC - xor the file bytes with the IV bytes
		for(i = 0; i < BUF_SIZE; i++){
			out_buffer[i] ^= chain_buffer[i];
		}

		//encrypt!
		rijndael_encrypt(out_buffer);

		len = fsOut->Write(out_buffer, BUF_SIZE);

		if (len < BUF_SIZE) {
			//'保存先に指定された暗号化ファイルに書き込めません。
			MsgText = LoadResourceString(&Msgencrypt::_MSG_ERROR_OUT_FILE_WRITE) + "\n" + OutFilePath;
			MsgType = mtError;
			MsgButtons = TMsgDlgButtons() << mbOK;
			MsgDefaultButton = mbOK;
			Synchronize(&PostConfirmMessageForm);
			goto LabelError;
		}

		for(i = 0; i < BUF_SIZE; i++){
			chain_buffer[i] = out_buffer[i];
			out_buffer[i] = 0;
		}

		z.next_out = out_buffer;    // 出力バッファ残量を元に戻す
		z.avail_out = BUF_SIZE;     // 出力ポインタを元に戻す

	}

	//-----------------------------------
	//進捗状況表示

	if (AllTotalSize == 0) {
		ProgressPercentNum = 100;
		ProgressPercentNumText = "100%";
	}
	else if (TotalSize == 0) {
		ProgressPercentNum = 0;
		ProgressPercentNumText = "0%";
	}
	else{
		ProgressPercentNumF = (float)TotalSize/AllTotalSize;
		ProgressPercentNum = (int)(ProgressPercentNumF*100);

		if (AllTotalSize < 104857600) {	// 100MB未満
			ProgressPercentNumText = IntToStr(ProgressPercentNum)+"%";
		}
		else{
			ProgressPercentNumText = FloatToStrF(ProgressPercentNumF*100, ffNumber, 4, 1)+"%";
		}
	}
	//-----------------------------------

	if ( fOpenIn == true ){
		ProgressMsgText = ExtractFileName(fsIn->FileName);
	}
	else{
		ProgressMsgText = ExtractFileName(OutFilePath);
	}


}//while(!Terminated);

if (Terminated == true) {
	//ユーザーキャンセルで抜けてきた
	goto LabelStop;
}

//残りのバッファ
if (z.avail_out > 0) {

		// PKCS #7 パディング
		len = BUF_SIZE - z.avail_out;

		paddingNum = (char)z.avail_out;
		for(i = len; i < BUF_SIZE; i++){
			out_buffer[i] = paddingNum;
		}

		// CBC - xor the file bytes with the IV bytes
		for(i = 0; i < BUF_SIZE; i++){
			out_buffer[i] ^= chain_buffer[i];
		}

		//encrypt!
		rijndael_encrypt(out_buffer);

		if ((len = fsOut->Write(out_buffer, BUF_SIZE)) != BUF_SIZE){
			//'保存先に指定された暗号化ファイルに書き込めません。
			MsgText = LoadResourceString(&Msgencrypt::_MSG_ERROR_OUT_FILE_WRITE) + "\n" + OutFilePath;
			MsgType = mtError;
			MsgButtons = TMsgDlgButtons() << mbOK;
			MsgDefaultButton = mbOK;
			Synchronize(&PostConfirmMessageForm);
			goto LabelError;
		}

}

if (deflateEnd(&z) != Z_OK){
	//zlibエラー
	goto LabelError;
}


//-----------------------------------
// 実行可能形式ファイルは
// 末尾へ暗号化データサイズを書き込む
//-----------------------------------
if ( fExeOutputOption == true ){
	ExeSize = fsOut->Seek((__int64)0, TSeekOrigin::soEnd);
	ExeSize = ExeSize-ExeAllSize;
	fsOut->Write(&ExeSize, sizeof(__int64));
}

//-----------------------------------
// 完了
//-----------------------------------
ProgressPercentNum = 100;
//'完了'
ProgressStatusText = LoadResourceString(&Msgencrypt::_LABEL_STATUS_TITLE_COMPLETE);
ProgressMsgText = ExtractFileName(OutFilePath);

if (fOpenIn == true) {
	delete fsIn;
}
if (fOpenOut == true) {
	delete fsOut;
}

//出力する暗号化ファイルのタイムスタンプを元ファイルに合わせる
if ( fKeepTimeStamp == true && first_fd.cFileName[0] != NULL ) {

	hFile = CreateFileW(FilePath.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL,
		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	if (hFile != INVALID_HANDLE_VALUE) {
		SetFileTime( hFile, &first_fd.ftCreationTime, &first_fd.ftLastAccessTime, &first_fd.ftLastWriteTime);
		CloseHandle(hFile);
	}
}

StatusNum = 1;
return;

//-----------------------------------
// エラーの後始末
//-----------------------------------
LabelError:

	ProgressPercentNum = 0;

	if ( status < 0 ){
		//'zlibライブラリからエラーを返されました。'
		//'エラー番号:'
		MsgText = LoadResourceString(&Msgencrypt::_MSG_ERROR_ZLIB) + IntToStr(status) + "\n" + z.msg;
		MsgType = mtError;
		MsgButtons = TMsgDlgButtons() << mbOK;
		MsgDefaultButton = mbOK;
		Synchronize(&PostConfirmMessageForm);
	}

	//'エラー'
	ProgressStatusText = LoadResourceString(&Msgencrypt::_LABEL_STATUS_TITLE_ERROR);
	//'暗号化に失敗しました。'
	ProgressMsgText = LoadResourceString(&Msgencrypt::_LABEL_STATUS_DETAIL_FAILED);

	if (fOpenIn == true) {
		delete fsIn;
	}
	if (fOpenOut == true) {
		delete fsOut;
	}

	StatusNum = -1;

	return;


//-----------------------------------
// ユーザーキャンセルの後始末
//-----------------------------------
LabelStop:

	ProgressPercentNum = 0;
	//'キャンセル'
	ProgressStatusText = LoadResourceString(&Msgencrypt::_LABEL_STATUS_TITLE_USER_CANCEL);
	//'暗号化が中止されました。'
	ProgressMsgText = LoadResourceString(&Msgencrypt::_LABEL_STATUS_DETAIL_STOPPED);

	if (fOpenIn == true) {
		delete fsIn;
	}
	if (fOpenOut == true) {
		delete fsOut;
	}

	StatusNum = -2;

	return;

}
Пример #11
0
/* Generate a temporary file name based on TMPL.  TMPL must match the
   rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
   does not exist at the time of the call to __gen_tempname.  TMPL is
   overwritten with the result.

   KIND may be one of:
   __GT_NOCREATE:       simply verify that the name does not exist
                        at the time of the call.
   __GT_FILE:           create the file using open(O_CREAT|O_EXCL)
                        and return a read-write fd.  The file is mode 0600.
   __GT_BIGFILE:        same as __GT_FILE but use open64().
   __GT_DIR:            create a directory, which will be mode 0700.

*/
int __gen_tempname (char *tmpl, int kind)
{
    char *XXXXXX;
    unsigned int k;
    int len, i, count, fd, save_errno = errno;
    unsigned char randomness[6];

    len = strlen (tmpl);
    if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
    {
	__set_errno (EINVAL);
	return -1;
    }

    /* This is where the Xs start.  */
    XXXXXX = &tmpl[len - 6];

    /* Get some random data.  */
	if (fillrand(randomness, sizeof(randomness)) != sizeof(randomness)) {
		/* if random device nodes failed us, lets use the braindamaged ver */
		brain_damaged_fillrand(randomness, sizeof(randomness));
    }
    for (i = 0 ; i < sizeof(randomness) ; i++) {
	k = ((randomness[i]) % 62);
	XXXXXX[i] = letters[k];
    }

    for (count = 0; count < TMP_MAX; ++count)
    {
	switch(kind) {
	    case __GT_NOCREATE:
		{
		    struct stat st;
		    if (stat (tmpl, &st) < 0)
		    {
			if (errno == ENOENT)
			{
			    __set_errno (save_errno);
			    return 0;
			}
			else
			    /* Give up now. */
			    return -1;
		    }
		    else
			continue;
		}
	    case __GT_FILE:
/* MOSS		fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
 * MOSE */
		if(create(tmpl, ATTR_FILE_DEFAULT) < 0)
			return -1 ;
		fd = open (tmpl, O_RDWR) ;
		break;
#if defined __UCLIBC_HAS_LFS__ // Should be compiled has LFS is not defined
	    case __GT_BIGFILE:
		fd = open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
		break;
#endif
	    case __GT_DIR:
/* MOSS		fd = mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
 * MOSE */
		fd = mkdir (tmpl, ATTR_DIR_DEFAULT | ATTR_TYPE_DIRECTORY) ;
		break;
	    default:
		fd = -1;
		assert (! "invalid KIND in __gen_tempname");
	}

	if (fd >= 0) {
	    __set_errno (save_errno);
	    return fd;
	}
	else if (errno != EEXIST)
	    /* Any other error will apply also to other names we might
	       try, and there are 2^32 or so of them, so give up now. */
	    return -1;
    }

    /* We got out of the loop because we ran out of combinations to try.  */
    __set_errno (EEXIST);
    return -1;
}
Пример #12
0
int encfile(struct my_FILE* fin, struct aes *ctx)
{   unsigned char   inbuf[16], outbuf[16];
    long int        flen;
    unsigned long   i=0, l=0;

    fillrand(outbuf, 16);             /* set an IV for CBC mode           */
    flen = fin->size;
//    fseek(fin, 0, SEEK_END);        /* get the length of the file       */
//    fgetpos(fin, (fpos_t*)&flen);   /* and then reset to start          */
//    fseek(fin, 0, SEEK_SET);

//    fwrite(outbuf, 1, 16, fout);    /* write the IV to the output       */
    fillrand(inbuf, 1);             /* make top 4 bits of a byte random */
    l = 15;                         /* and store the length of the last */
                                    /* block in the lower 4 bits        */
    inbuf[0] = ((char)flen & 15) | (inbuf[0] & ~15);

    _Pragma( "loopbound min 1961 max 1961" )
    while(!my_feof(fin))               /* loop to encrypt the input file   */
    {                                  /* input 1st 16 bytes to buf[1..16] */
        i = my_fread(inbuf + 16 - l, 1, l, fin);  /*  on 1st round byte[0] */
                                                  /* is the length code    */
        if(i < l) break;               /* if end of the input file reached */

        _Pragma( "loopbound min 16 max 16" )
        for(i = 0; i < 16; ++i)        /* xor in previous cipher text      */
            inbuf[i] ^= outbuf[i];

        encrypt(inbuf, outbuf, ctx);   /* and do the encryption            */

//        if(fwrite(outbuf, 1, 16, fout) != 16) {
//          printf("Error writing to output file: %s\n", fn);
//          return -7;
//        }
                                    /* in all but first round read 16   */
        l = 16;                     /* bytes into the buffer            */
    }

    /* except for files of length less than two blocks we now have one  */
    /* byte from the previous block and 'i' bytes from the current one  */
    /* to encrypt and 15 - i empty buffer positions. For files of less  */
    /* than two blocks (0 or 1) we have i + 1 bytes and 14 - i empty    */
    /* buffer position to set to zero since the 'count' byte is extra   */

    if(l == 15)                         /* adjust for extra byte in the */
        ++i;                            /* in the first block           */

    if(i)                               /* if bytes remain to be output */
    {
        _Pragma( "loopbound min 6 max 6" )
        while(i < 16)                   /* clear empty buffer positions */
          inbuf[i++] = 0;

        _Pragma( "loopbound min 16 max 16" )
        for(i = 0; i < 16; ++i)         /* xor in previous cipher text  */
            inbuf[i] ^= outbuf[i]; 

        encrypt(inbuf, outbuf, ctx);    /* encrypt and output it        */

//        if(fwrite(outbuf, 1, 16, fout) != 16) {
//          printf("Error writing to output file: %s\n", fn);
//          return -8;
//        }
    }
    return 0;
}
Пример #13
0
int main(int argc, char **argv)
{
  gdata l;
  int k, w, i, j, m;
  int *matrix;
  char **data, **coding;
  int *erasures, *erased;
  int *decoding_matrix, *dm_ids;
  struct jerasure_context *ctx;
  
  if (argc != 4) usage(NULL);
  if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k");
  if (sscanf(argv[2], "%d", &m) == 0 || m <= 0) usage("Bad m");
  if (sscanf(argv[3], "%d", &w) == 0 || (w != 8 && w != 16 && w != 32)) usage("Bad w");
  if (w <= 16 && k + m > (1 << w)) usage("k + m is too big");

  ctx = jerasure_make_context(w);
  matrix = reed_sol_vandermonde_coding_matrix(ctx, k, m);

  printf("Last m rows of the Distribution Matrix:\n\n");
  jerasure_print_matrix(matrix, m, k, w);
  printf("\n");

  srand48(0);
  data = talloc(char *, k);
  for (i = 0; i < k; i++) {
    data[i] = talloc(char, sizeof(gdata));
    fillrand(data[i], sizeof(gdata));
  }

  coding = talloc(char *, m);
  for (i = 0; i < m; i++) {
    coding[i] = talloc(char, sizeof(gdata));
  }

  jerasure_matrix_encode(ctx, k, m, matrix, data, coding, sizeof(gdata));
  
  printf("Encoding Complete:\n\n");
  print_data_and_coding_1(k, m, w, sizeof(gdata), data, coding);

  erasures = talloc(int, (m+1));
  erased = talloc(int, (k+m));
  for (i = 0; i < m+k; i++) erased[i] = 0;
  l = 0;
  for (i = 0; i < m; ) {
    erasures[i] = lrand48()%(k+m);
    if (erased[erasures[i]] == 0) {
      erased[erasures[i]] = 1;
      memcpy((erasures[i] < k) ? data[erasures[i]] : coding[erasures[i]-k], &l, sizeof(gdata));
      i++;
    }
  }
  erasures[i] = -1;

  printf("Erased %d random devices:\n\n", m);
  print_data_and_coding_1(k, m, w, sizeof(gdata), data, coding);
  
  i = jerasure_matrix_decode(ctx, k, m, matrix, 1, erasures, data, coding, sizeof(gdata));

  printf("State of the system after decoding:\n\n");
  print_data_and_coding_1(k, m, w, sizeof(gdata), data, coding);
  /* free data to avoid false positives for leak testing */
  free(erased);
  free(erasures);
  for (i = 0; i < m; i++) {
    free(coding[i]);
  }
  free(coding);
  for (i = 0; i < k; i++) {
    free(data[i]);
  }
  free(data);
  free(matrix);
  jerasure_release_context(ctx);

  return 0;
}
Пример #14
0
int encfile(FILE *fin, FILE *fout, aes_ctx *ctx, const char* ifn, const char* ofn)
{   char            buf[BLOCK_LEN], dbuf[2 * BLOCK_LEN];
    fpos_t          flen;
    unsigned long   i, len, rlen;

    // set a random IV

    fillrand(dbuf, BLOCK_LEN);

    // find the file length

    fseek(fin, 0, SEEK_END);
    fgetpos(fin, &flen); 
    rlen = file_len(flen);
    // reset to start
    fseek(fin, 0, SEEK_SET);

    if(rlen <= BLOCK_LEN)               
    {   // if the file length is less than or equal to 16 bytes
        
        // read the bytes of the file into the buffer and verify length
        len = (unsigned long) fread(dbuf + BLOCK_LEN, 1, BLOCK_LEN, fin);
        rlen -= len;        
        if(rlen > 0) 
            return READ_ERROR;

        // pad the file bytes with zeroes
        for(i = len; i < BLOCK_LEN; ++i)
            dbuf[i + BLOCK_LEN] = 0;

        // xor the file bytes with the IV bytes
        for(i = 0; i < BLOCK_LEN; ++i)
            dbuf[i + BLOCK_LEN] ^= dbuf[i];

        // encrypt the top 16 bytes of the buffer
        aes_enc_blk(dbuf + BLOCK_LEN, dbuf + len, ctx);

        len += BLOCK_LEN;
        // write the IV and the encrypted file bytes
        if(fwrite(dbuf, 1, len, fout) != len)
            return WRITE_ERROR;
    }
    else
    {   // if the file length is more 16 bytes
        
        // write the IV
        if(fwrite(dbuf, 1, BLOCK_LEN, fout) != BLOCK_LEN)
            return WRITE_ERROR;

        // read the file a block at a time 
        while(rlen > 0 && !feof(fin))
        {  
            // read a block and reduce the remaining byte count
            len = (unsigned long)fread(buf, 1, BLOCK_LEN, fin);
            rlen -= len;

            // verify length of block 
            if(len != BLOCK_LEN) 
                return READ_ERROR;

            // do CBC chaining prior to encryption
            for(i = 0; i < BLOCK_LEN; ++i)
                buf[i] ^= dbuf[i];

            // encrypt the block
            aes_enc_blk(buf, dbuf, ctx);

            // if there is only one more block do ciphertext stealing
            if(rlen > 0 && rlen < BLOCK_LEN)
            {
                // move the previous ciphertext to top half of double buffer
                // since rlen bytes of this are output last
                for(i = 0; i < BLOCK_LEN; ++i)
                    dbuf[i + BLOCK_LEN] = dbuf[i];

                // read last part of plaintext into bottom half of buffer
                if(fread(dbuf, 1, rlen, fin) != rlen)
                    return READ_ERROR;

                // clear the remainder of the bottom half of buffer
                for(i = 0; i < BLOCK_LEN - rlen; ++i)
                    dbuf[rlen + i] = 0;

                // do CBC chaining from previous ciphertext
                for(i = 0; i < BLOCK_LEN; ++i)
                    dbuf[i] ^= dbuf[i + BLOCK_LEN];

                // encrypt the final block
                aes_enc_blk(dbuf, dbuf, ctx);

                // set the length of the final write
                len = rlen + BLOCK_LEN; rlen = 0;
            }

            // write the encrypted block
            if(fwrite(dbuf, 1, len, fout) != len)
                return WRITE_ERROR;
        }
    }

    return 0;
}