メインページ | アルファベット順一覧 | 構成 | ファイル一覧 | 構成メンバ | ファイルメンバ | 関連ページ

# dkcSafeFileSystem.c

説明を見る。

    00001
    00007 #define DKUTIL_C_SAFE_FILESYSTEM_C
    00008 #include "dkcSafeFileSystem.h"
    00009 #include "dkcMath.h"
    00010 #include "dkcStdio.h"
    00011
    00012 static DKC_INLINE int HeaderWrite(DKC_STREAM *p,DKC_FILE_HEADER_FILE_WITH_SIGNATURE  *header)
    00013 {
    00014     BYTE isLE = (BYTE)dkcIsLittleEndian();
    00015     if(header->little_endian != isLE)
    00016     {//ココバグっているかも･･･。
    00017         header->sig = dkcReverseEndian32(header->sig);
    00018         header->filesize = dkcReverseEndian64(header->filesize);
    00019     }
    00020     return dkcStreamWrite(p,header,sizeof(DKC_FILE_HEADER_FILE_WITH_SIGNATURE));
    00021 }
    00022
    00023
    00024 static DKC_INLINE int GetHeader(
    00025     DKC_FILE_HEADER_FILE_WITH_SIGNATURE *header,
    00026     const char *filename)
    00027 {
    00028     size_t readsize = 0;
    00029     size_t mustsize = sizeof(DKC_FILE_HEADER_FILE_WITH_SIGNATURE);
    00030     int r = edk_FAILED;
    00031     FILE *fp = NULL;
    00032     BYTE isLE = (BYTE)dkcIsLittleEndian();
    00033     //BYTE get_flag;
    00034     const char *mode = "rb";
    00035
    00036     fp = dkcFOpen(filename,mode);
    00037     if(NULL==fp){
    00038         goto Exit;
    00039     }
    00040     fseek(fp,0,SEEK_SET);
    00041     //readsize = fread(header,1,mustsize,fp);
    00042     readsize = dkcFReadAll(header,mustsize,fp);
    00043     if(mustsize != readsize){
    00044         goto Exit;
    00045     }
    00046
    00047     if(header->little_endian != isLE)
    00048     {//エンディアンが違ったらリバース
    00049         header->sig = dkcReverseEndian32(header->sig);
    00050         header->filesize = dkcReverseEndian64(header->filesize);
    00051     }
    00052
    00053
    00054     r = edk_SUCCEEDED;
    00055 Exit:
    00056     dkcFClose(&fp);
    00057     return r;
    00058     /*
    00059     DKC_STREAM *fsp;
    00060
    00061     //読み込み時
    00062     fsp = dkcAllocStreamFileType(edkcStreamRead,filename,mode);
    00063     if(NULL==fsp){
    00064         return edk_FAILED;
    00065     }
    00066     r = dkcStreamRead(fsp,header,mustsize,&readsize);
    00067     if(DKUTIL_FAILED(r)){
    00068         return r;
    00069     }
    00070     if(readsize != mustsize){
    00071         return edk_FAILED;
    00072     ]
    00073     dkcFreeStream(&fsp);
    00074     */
    00075 }
    00076
    00077
    00078 //flagにはエンディアンを
    00079 /*
    00080 int WINAPI dkcFileWithSignatureCheckCheatFile(UINT flag,const char *filename){
    00081     //チェックオブジェクト
    00082     DKC_STREAM *sp;
    00083     DKC_SHA1 *sha;
    00084     //戻り値
    00085     int r;
    00086     //バッファとか
    00087     BYTE buff[2048];
    00088     size_t i;
    00089
    00090     flag |= edkcStreamProcessAsOrdered;
    00091
    00092     sp = dkcAllocStreamFileType(flag,filename,"rb");
    00093
    00094     if(NULL==sp){
    00095         return edk_FAILED;
    00096     }
    00097     sha = dkcAllocSHA1();
    00098     if(NULL==sha){
    00099         goto Exit;
    00100     }
    00101
    00102     dkcStreamRead(sp,buff,sizeof(buff),
    00103 Exit:
    00104     dkcFreeSHA1(&sha);
    00105     dkcFreeStream(&sp);
    00106     return r;
    00107 }*/
    00108
    00109 #ifdef _MSC_VER
    00110 #   pragma warning(disable:4701)
    00111 #endif
    00112
    00113 DKC_FILE_WITH_SIGNATURE *WINAPI dkcOpenFileWithSignature(
    00114 /*
    00115     UINT flag,size_t size,
    00116     const char *filename,const char *mode,
    00117     const void *dustbin,size_t dustbin_size
    00118 */
    00119     UINT stream_flag,
    00120     const char *filename,const char *mode,
    00121     const void *dustbin,size_t dustbin_size,
    00122     UINT signature
    00123 )
    00124 {
    00125     DKC_STREAM *sp = NULL;
    00126     void *tp = NULL;
    00127     DKC_BUFFER *mbp = NULL;
    00128     DKC_FILE_WITH_SIGNATURE *p = NULL;
    00129
    00130     DKC_FILE_HEADER_FILE_WITH_SIGNATURE header;
    00131
    00132     BOOL isWrite = FALSE;
    00133     BYTE isLE = (BYTE)dkcIsLittleEndian();
    00134
    00135     //UINT stream_flag = edkcStreamInitFile;
    00136
    00137     //フラグの変更
    00138     stream_flag |= edkcStreamInitFile;
    00139
    00140     DKUTIL_FLAG_DOWN(stream_flag,edkcStreamInitMemory);
    00141
    00142     DKUTIL_FLAG_DOWN(stream_flag,edkcStreamProcessDefault);
    00143
    00144     DKUTIL_FLAG_UP(stream_flag,edkcStreamProcessAsOrdered);
    00145
    00146     //size_t stream_size;
    00147
    00148
    00149     //エラーチェック
    00150     if(NULL==dustbin ||  0 == dustbin_size){
    00151         return NULL;
    00152     }
    00153
    00154     if(NULL==mode || NULL==filename){
    00155         return NULL;
    00156     }
    00157     if(NULL != strchr(mode,'a')){//共通モードでは開けない
    00158         return NULL;
    00159     }
    00160     if(NULL != strchr(mode,'t')){//テキストモードでは開けない。
    00161         return NULL;
    00162     }
    00163
    00164
    00165     //領域取得
    00166
    00167     p = (DKC_FILE_WITH_SIGNATURE *)dkcAllocate(sizeof(DKC_FILE_WITH_SIGNATURE));
    00168     if(NULL==p){
    00169         return NULL;
    00170     }
    00171     tp = (DKC_SHA1 *)dkcAllocSHA1();
    00172     if(NULL==tp){
    00173         goto Error;
    00174     }
    00175
    00176     //ライトモードかどうか。
    00177     isWrite = (NULL==strchr(mode,'r'));
    00178
    00179     if(isWrite){
    00180         //書き込みモードの時
    00181         p->mWriteMode = TRUE;
    00182     }else{
    00183         if(DKUTIL_FAILED(GetHeader(&header,filename))){
    00184             goto Error;
    00185         }
    00186
    00187         if(header.little_endian){
    00188             stream_flag |= edkcStreamLittleEndian;
    00189         }else{
    00190             stream_flag |= edkcStreamBigEndian;
    00191         }
    00192
    00193         p->mWriteMode = FALSE;
    00194         //とりあえず、コピーしておかないと支障が出る。
    00195         memcpy(&(p->mFileHeader),&header,sizeof(header));
    00196     }
    00197
    00198
    00199     sp = dkcAllocStreamFileType( stream_flag,filename,mode);
    00200     if(NULL==sp){
    00201         goto Error;
    00202     }
    00203     //update
    00204     p->mStream = sp;
    00205
    00206     if(isWrite){
    00207         //ヘッダ分を書き込んでおく。
    00208         memset(&header,0,sizeof(header));
    00209         dkcStreamWrite(sp,&header,sizeof(header));
    00210
    00211
    00212         //ヘッダの設定
    00213
    00214         //エンディアン設定
    00215         if(isLE){
    00216             if(FALSE==p->mStream->mChangeEndian){
    00217                 p->mFileHeader.little_endian = TRUE;
    00218             }else{
    00219                 p->mFileHeader.little_endian = FALSE;
    00220             }
    00221         }else{
    00222             if(TRUE==p->mStream->mChangeEndian){
    00223                 p->mFileHeader.little_endian = TRUE;
    00224             }else{
    00225                 p->mFileHeader.little_endian = FALSE;
    00226             }
    00227         }
    00228         //シグネチャを設定
    00229         p->mFileHeader.sig = signature;
    00230     }
    00231
    00232     mbp = dkcAllocBuffer(dustbin,dustbin_size);
    00233     if(NULL==mbp){
    00234         goto Error;
    00235     }
    00236
    00237
    00238
    00239     p->mSHA1 = (DKC_SHA1 *)tp;
    00240     p->mDustbin = mbp;
    00241
    00242     //とりあえず、ゴミ値をSHA1にロード
    00243     dkcSHA1Load(p->mSHA1,(const BYTE *)dustbin,dustbin_size);
    00244
    00245     if(isWrite==FALSE){
    00246         //ストリームをデータ部にシーク
    00247         dkcStreamSeek(p->mStream,sizeof(DKC_FILE_HEADER_FILE_WITH_SIGNATURE),edkcStreamSeekSet);
    00248     }
    00249
    00250
    00251     return p;
    00252 Error:
    00253     dkcFreeStream(&sp);
    00254     dkcFreeSHA1((DKC_SHA1 **)&tp);
    00255     dkcFree((void **)&p);
    00256     return NULL;
    00257 }
    00258
    00259 #ifdef _MSC_VER
    00260 #   pragma warning(default:4701)
    00261 #endif
    00262
    00264 static DKC_INLINE BOOL FileWithSignatureIsFinalized(DKC_FILE_WITH_SIGNATURE *ptr){
    00265     return ptr->mSHA1->mFinalized;
    00266 }
    00267
    00269 static DKC_INLINE int FileWithSignatureGetDigest(DKC_FILE_WITH_SIGNATURE *ptr
    00270                                                                                                  //,BYTE *buff,size_t size
    00271                                                                                                  )
    00272 {
    00273     dkcSHA1Load(
    00274         ptr->mSHA1,
    00275         dkcBufferPointer(ptr->mDustbin),
    00276         dkcBufferSize(ptr->mDustbin)
    00277     );
    00278     return dkcSHA1FinalDigest(
    00279         ptr->mSHA1,
    00280         ptr->mFileHeader.hash_value,
    00281         sizeof(ptr->mFileHeader.hash_value)
    00282     );
    00283 }
    00284
    00285 int WINAPI dkcCloseFileWithSignature(DKC_FILE_WITH_SIGNATURE **p){
    00286     DKC_FILE_WITH_SIGNATURE *ptr;
    00287     //BYTE buff[SHA1_BUFFER_SIZE];
    00288
    00289     //size_t offset = SM_OFFSET(DKC_FILE_HEADER_FILE_WITH_SIGNATURE,hash_value);
    00290
    00291     if(NULL==p){
    00292         return edk_FAILED;
    00293     }
    00294
    00295     ptr = *p;
    00296
    00297     if(ptr->mWriteMode)
    00298     {//書き込みモード時のみ
    00299
    00300         //メッセージダイジェストを取得
    00301         //FileWithSignatureGetDigest(ptr,buff,sizeof(buff));
    00302         FileWithSignatureGetDigest(ptr);
    00303         //ファイルサイズ取得
    00304         ptr->mFileHeader.filesize = (ULONGLONG)dkcStreamTell(ptr->mStream);
    00305         //ptr->mFileHeader.datasize = ptr->mFileHeader.filesize - sizeof(DKC_FILE_HEADER_FILE_WITH_SIGNATURE);
    00306
    00307         //メッセージダイジェスト領域の位置を取得
    00308         dkcStreamSeek(ptr->mStream,0,edkcStreamSeekSet);
    00309         //メッセージダイジェストを書き込む
    00310         //dkcStreamWrite(ptr->mStream,buff,sizeof(buff));
    00311         HeaderWrite(ptr->mStream,&(ptr->mFileHeader));
    00312     }
    00313     dkcFreeBuffer(&(ptr->mDustbin));
    00314
    00315     dkcFreeStream(&(ptr->mStream));
    00316
    00317     dkcFreeSHA1(&(ptr->mSHA1));
    00318
    00319     return dkcFree((void **)p);
    00320 }
    00321
    00322 typedef int (WINAPI *CALLBACK_WRITE_F_T)(DKC_STREAM *,const void *,size_t);
    00323
    00324 typedef struct FileWithSigCallBackSend{
    00325     DKC_FILE_WITH_SIGNATURE *psig;
    00326     size_t readsize;
    00327     CALLBACK_WRITE_F_T callback;
    00328 }FWS_CALLBACK_SEND;
    00329
    00330 static int WINAPI WriteCallback(DKC_STREAM *ptr,void *buffer,size_t size,void *data){
    00331     int r;
    00332     FWS_CALLBACK_SEND *pfws = (FWS_CALLBACK_SEND *)data;
    00333     CALLBACK_WRITE_F_T callback = pfws->callback;
    00334
    00335     r = callback(ptr,buffer,size);
    00336
    00337     if(DKUTIL_FAILED(r)){
    00338         return r;
    00339     }
    00340     dkcSHA1Load(pfws->psig->mSHA1,(const BYTE *)buffer,size);
    00341     return r;
    00342 }
    00343
    00344 static int WINAPI ReadCallback(DKC_STREAM *ptr,void *buffer,size_t size,void *data){
    00345
    00346     int r;
    00347     FWS_CALLBACK_SEND *pfws = (FWS_CALLBACK_SEND *)data;
    00348     size_t readsize;
    00349
    00350     r = dkcStreamRead(ptr,buffer,size,&readsize);
    00351     (pfws->readsize) = readsize;
    00352
    00353     if(DKUTIL_FAILED(r)){
    00354         return r;
    00355     }
    00356     dkcSHA1Load(pfws->psig->mSHA1,(const BYTE *)buffer,readsize);
    00357
    00358     return r;
    00359 }
    00360
    00361
    00362 static DKC_INLINE int FileWithSignatureReadLogic(DKC_FILE_WITH_SIGNATURE *p,
    00363                                                                         void *data,size_t size,size_t *readsize){
    00364     FWS_CALLBACK_SEND send;
    00365     int r;
    00366     send.callback = NULL;
    00367     send.psig = p;
    00368     send.readsize = 0;
    00369     r = dkcStreamProcess(p->mStream,data,size,ReadCallback,(void *)&send);
    00370     if(readsize){
    00371         *readsize = send.readsize;
    00372     }
    00373     return r;
    00374     /*
    00375     int r;
    00376     size_t readsize_ = 0;
    00377     if(NULL==readsize){
    00378         readsize = &readsize_;
    00379     }
    00380
    00381     r = dkcStreamRead(p->mStream,data,size,readsize);
    00382     if(DKUTIL_FAILED(r)){
    00383         return r;
    00384     }
    00385     dkcSHA1Load(p->mSHA1,data,*readsize);
    00386     return r;
    00387     */
    00388 }
    00389
    00390 static DKC_INLINE int FileWithSignatureWriteLogic(DKC_FILE_WITH_SIGNATURE *p,
    00391                                                                          const void *data,size_t size,CALLBACK_WRITE_F_T callback)
    00392 {
    00393     //return WriteCallback(p->mStream,data,size,&send);
    00394     /*int r;
    00395     r = callback(p->mStream,data,size);
    00396     if(DKUTIL_FAILED(r)){
    00397         return r;
    00398     }
    00399     dkcSHA1Load(p->mSHA1,data,size);
    00400
    00401     return r;
    00402     */
    00403 }
    00404
    00405
    00406 static DKC_INLINE int ReadEOFCheck(DKC_FILE_WITH_SIGNATURE *p){
    00407     ULONGLONG filesize = p->mFileHeader.filesize;
    00408     ULONGLONG stream_size = dkcStreamTell(p->mStream);
    00409     if(filesize == stream_size || TRUE==p->mAllLoad)
    00410     {
    00411         p->mAllLoad = TRUE;
    00412         return edk_EndProcess;
    00413     }
    00414     return edk_SUCCEEDED;
    00415 }
    00416
    00417 int WINAPI dkcFileWithSignatureRead(DKC_FILE_WITH_SIGNATURE *p,
    00418                                                                         void *data,size_t size,size_t *readsize){
    00419     size_t tsize;
    00420     ULONGLONG filesize = p->mFileHeader.filesize;
    00421     ULONGLONG stream_size = dkcStreamTell(p->mStream);
    00422     int r = edk_FAILED;
    00423
    00424     if(readsize){
    00425         //とりあえず、明示的にまだ読み込んでいない事を告げる。
    00426         *readsize = 0;
    00427     }
    00428
    00429     if(p->mWriteMode){//書き込みモードじゃねぇかよ。
    00430         return edk_LogicError;
    00431     }
    00432
    00433     if(filesize == stream_size || TRUE==p->mAllLoad)
    00434     {
    00435         p->mAllLoad = TRUE;
    00436         return edk_EndProcess;
    00437     }
    00438     //ファイルに冗長なモノが引っ付いている。
    00439     if(filesize < stream_size){
    00440         p->mAllLoad = TRUE;
    00441         return edk_FileCheated_Addition;
    00442     }
    00443     //読み取りサイズをフィルターする
    00444     if(stream_size + size > filesize){
    00445         tsize = (size_t)(ULONGLONG)(filesize - stream_size);
    00446     }else{
    00447         tsize = size;
    00448     }
    00449
    00450     r = FileWithSignatureReadLogic(
    00451         p,data,tsize,readsize);
    00452
    00453
    00454     if(DKUTIL_FAILED(r)){
    00455         return r;
    00456     }
    00457
    00458     return ReadEOFCheck(p);
    00459     //return dkcStreamRead(p->mStream,data,tsize,readsize);
    00460 }
    00461
    00462
    00463 int WINAPI dkcFileWithSignatureWrite(DKC_FILE_WITH_SIGNATURE *p,
    00464                                                                          const void *data,size_t size)
    00465 {
    00466     FWS_CALLBACK_SEND send;
    00467     send.callback = dkcStreamWrite;
    00468     send.psig = p;
    00469     send.readsize = 0;
    00470     return dkcStreamProcess(p->mStream,(void *)data,size,WriteCallback,&send);
    00471     //return FileWithSignatureWriteLogic(p,data,size,dkcStreamWrite);
    00472
    00473 }
    00474
    00475 int WINAPI dkcFileWithSignatureWrite16(DKC_FILE_WITH_SIGNATURE *p,
    00476                                                                              const void *data,size_t size)
    00477 {
    00478     FWS_CALLBACK_SEND send;
    00479     send.callback = dkcStreamWrite16;
    00480     send.psig = p;
    00481     send.readsize = 0;
    00482     return dkcStreamProcess(p->mStream,(void *)data,size,WriteCallback,&send);
    00483     //return FileWithSignatureWriteLogic(p,data,size,dkcStreamWrite16);
    00484 }
    00485
    00486
    00487
    00488 int WINAPI dkcFileWithSignatureWrite32(DKC_FILE_WITH_SIGNATURE *p,
    00489                                                                                                 const void *data,size_t size)
    00490 {
    00491     FWS_CALLBACK_SEND send;
    00492     send.callback = dkcStreamWrite32;
    00493     send.psig = p;
    00494     send.readsize = 0;
    00495     return dkcStreamProcess(p->mStream,(void *)data,size,WriteCallback,&send);
    00496     //return FileWithSignatureWriteLogic(p,data,size,dkcStreamWrite32);
    00497 }
    00498
    00499 int WINAPI dkcFileWithSignatureWrite64(DKC_FILE_WITH_SIGNATURE *p,
    00500                                                                                                 const void *data,size_t size)
    00501 {
    00502     FWS_CALLBACK_SEND send;
    00503     send.callback = dkcStreamWrite64;
    00504     send.psig = p;
    00505     send.readsize = 0;
    00506     return dkcStreamProcess(p->mStream,(void *)data,size,WriteCallback,&send);
    00507     //return FileWithSignatureWriteLogic(p,data,size,dkcStreamWrite64);
    00508 }
    00509
    00510 int WINAPI dkcFileWithSignatureCheckCheat(DKC_FILE_WITH_SIGNATURE *p){
    00511     ULONGLONG filesize = p->mFileHeader.filesize;
    00512     ULONGLONG stream_size = dkcStreamTell(p->mStream);
    00513     BYTE buff[SHA1_BIN_BUFFER_SIZE];
    00514     int r;
    00515
    00516     if(FALSE==p->mAllLoad){//すべて読み込んでいない。
    00517         return edk_LogicError;
    00518     }
    00519     if(TRUE==p->mWriteMode){//書き込みモード時は使用できない。
    00520         return edk_LogicError;
    00521     }
    00522
    00523     dkcSHA1Load(p->mSHA1,
    00524         dkcBufferPointer(p->mDustbin),
    00525         dkcBufferSize(p->mDustbin)
    00526     );
    00527
    00528     //メッセージダイジェストが欲しい。（二回呼び出されてもOK）
    00529     dkcSHA1FinalDigest(p->mSHA1,buff,sizeof(buff));
    00530
    00531     r = dkc_memcmp(
    00532         buff,sizeof(buff),
    00533         p->mFileHeader.hash_value,sizeof(p->mFileHeader.hash_value));
    00534
    00535     if(DKUTIL_FAILED(r)){//違うみたい〜〜。
    00536         return edk_SignatureException;
    00537     }
    00538
    00539     if(filesize < stream_size){//サイズが違う〜〜。へんなもの引っ付いている〜〜。
    00540         return edk_FileCheated_Addition;
    00541     }
    00542     if(filesize == stream_size){
    00543         return edk_SUCCEEDED;
    00544     }
    00545     //誰だよ、チートしたのは･･･。
    00546     return edk_FAILED;
    00547
    00548 }
    00549
    00550 /*
    00551
    00552 BOOL WINAPI dkcFileWithSignatureIsEOF(DKC_FILE_WITH_SIGNATURE *p);
    00553
    00554 BOOL WINAPI dkcFileWithSignatureIsError(DKC_FILE_WITH_SIGNATURE *p);
    00555
    00556 //@return 改竄されていたらTRUE
    00557 BOOL WINAPI dkcFileWithSignatureIsCheated(DKC_FILE_WITH_SIGNATURE *p){
    00558     if(p->mSHA1->mFinalized){
    00559         dkcmNOT_ASSERT("ERROR");
    00560         return edk_LogicError;
    00561     }
    00562     p->mSHA1
    00563
    00564 }
    00565
    00566 */