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
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
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
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 #ifdef _MSC_VER
00110 # pragma warning(disable:4701)
00111 #endif
00112
00113 DKC_FILE_WITH_SIGNATURE *WINAPI dkcOpenFileWithSignature(
00114
00115
00116
00117
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
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
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
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
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
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
00288
00289
00290
00291 if(NULL==p){
00292 return edk_FAILED;
00293 }
00294
00295 ptr = *p;
00296
00297 if(ptr->mWriteMode)
00298 {
00299
00300
00301
00302 FileWithSignatureGetDigest(ptr);
00303
00304 ptr->mFileHeader.filesize = (ULONGLONG)dkcStreamTell(ptr->mStream);
00305
00306
00307
00308 dkcStreamSeek(ptr->mStream,0,edkcStreamSeekSet);
00309
00310
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
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
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
00394
00395
00396
00397
00398
00399
00400
00401
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
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
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
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
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
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
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
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566