/****************************************************************************** * * NSSDC/CDF CDF `check sum' operations. * * Version 1.0, 21-Mar-06, Hughes STX. * * Modification history: * * V1.0 21-Mar-06, M Liu Original version. ******************************************************************************/ #include "cdflib.h" #include "cdflib64.h" #include "cdfmd5.h" #define BUFFSIZE 16384 /****************************************************************************** * Local function prototypes. ******************************************************************************/ CDFstatus AddChecksumMD5 PROTOARGs((vFILE *vFp, long size, unsigned char *signature)); CDFstatus AddChecksumMD5_64 PROTOARGs((vFILE *vFp, OFF_T size, unsigned char *signature)); CDFstatus ComputeChecksumMD5 PROTOARGs((vFILE *vFp, long size, unsigned char *signature)); CDFstatus ComputeChecksumMD5_64 PROTOARGs((vFILE *vFp, OFF_T size, unsigned char *signature)); CDFstatus GetChecksumMD5 PROTOARGs((vFILE *vFp, long size, unsigned char *signature)); CDFstatus GetChecksumMD5_64 PROTOARGs((vFILE *vFp, OFF_T size, unsigned char *signature)); CDFstatus AddChecksum PROTOARGs((struct CDFstruct *CDF)); CDFstatus AddChecksum64 PROTOARGs((struct CDFstruct *CDF)); CDFstatus VerifyChecksum PROTOARGs((struct CDFstruct *CDF)); CDFstatus VerifyChecksum64 PROTOARGs((struct CDFstruct *CDF)); /****************************************************************************** * AddChecksumMD5. ******************************************************************************/ CDFstatus AddChecksumMD5 (vFp, size, signature) vFILE *vFp; long size; unsigned char signature[16]; { #if defined(vms) size_t lastBlk; unsigned char buffer[512]; int i, j, inBlk, cross= 0; inBlk = size % 512; lastBlk = (size_t) 512 * (size / 512); if (inBlk != 0) { if (fseek(vFp->fp,lastBlk,SEEK_SET) == EOF) { return FALSE; } for (i = 0; i < 512; i++) buffer[i] = 0; if (fread(buffer,512,1,vFp->fp) != 1) { return FALSE; } for (i = 0; i < 16; i++) { j = inBlk + i; if (j > 511) { cross = i; break; } buffer[j] = signature[i]; } if (fseek(vFp->fp,lastBlk,SEEK_SET) == EOF) { return FALSE; } if (fwrite(buffer,512,1,vFp->fp) != 1) { return FALSE; } if (cross > 0) { for (i = 0; i < 512; i++) buffer[i] = 0; j = 0; for (i = cross; i < 16; i++) { buffer[j] = signature[i]; j++; } if (fwrite(buffer,512,1,vFp->fp) != 1) { return FALSE; } } } else { for (i = 16; i < 512; i++) buffer[i] = 0; for (i = 0; i < 16; i++) buffer[i] = signature[i]; if (fseek(vFp->fp,size,SEEK_SET) == EOF) { return FALSE; } if (fwrite(buffer,512,1,vFp->fp) != 1) { return FALSE; } } #else if (fseek(vFp->fp,size,vSEEK_SET) == EOF) return FALSE; if (fwrite(signature,1,16,vFp->fp) != 16) return FALSE; #endif if (fflush(vFp->fp) == EOF) { vFp->error = TRUE; return FALSE; } return TRUE; } /****************************************************************************** * AddChecksumMD5_64. ******************************************************************************/ CDFstatus AddChecksumMD5_64 (vFp, size, signature) vFILE *vFp; OFF_T size; unsigned char signature[16]; { #if defined(win32) && (_FILE_OFFSET_BITS == 64) if (vFp->fh == 0) return FALSE; if (FSEEK64(vFp->fh,(OFF_T) size,vSEEK_SET) == EOF) return FALSE; if (FWRITE64(vFp->fh,signature,16) != 16) return FALSE; if (FLUSH64(vFp->fh) == EOF) { vFp->error = TRUE; return FALSE; } #else if (vFp->fp == NULL) return FALSE; #if defined(vms) OFF_T lastBlk; unsigned char buffer[512]; int i, j, inBlk, cross= 0; inBlk = size % 512; lastBlk = (OFF_T) 512 * (size / 512); if (inBlk != 0) { if (FSEEK64(vFp->fp,lastBlk,SEEK_SET) == EOF) { vFp->error = TRUE; return FALSE; } for (i = 0; i < 512; i++) buffer[i] = 0; if (FREAD64(buffer,512,1,vFp->fp) != 1) { vFp->error = TRUE; return FALSE; } for (i = 0; i < 16; i++) { j = inBlk + i; if (j > 511) { cross = i; break; } buffer[j] = signature[i]; } if (FSEEK64(vFp->fp,lastBlk,SEEK_SET) == EOF) { vFp->error = TRUE; return FALSE; } if (FWRITE64(buffer,512,1,vFp->fp) != 1) { vFp->error = TRUE; return FALSE; } if (cross > 0) { for (i = 0; i < 512; i++) buffer[i] = 0; j = 0; for (i = cross; i < 16; i++) { buffer[j] = signature[i]; j++; } if (FWRITE64(buffer,512,1,vFp->fp) != 1) { vFp->error = TRUE; return FALSE; } } } else { for (i = 16; i < 512; i++) buffer[i] = 0; for (i = 0; i < 16; i++) buffer[i] = signature[i]; if (FSEEK64(vFp->fp,size,SEEK_SET) == EOF) { vFp->error = TRUE; return FALSE; } if (FWRITE64(buffer,512,1,vFp->fp) != 1) { vFp->error = TRUE; return FALSE; } } #else if (FSEEK64(vFp->fp,(OFF_T) size,vSEEK_SET) == EOF) return FALSE; if (FWRITE64(signature,1,16,vFp->fp) != 16) return FALSE; #endif if (FLUSH64(vFp->fp) == EOF) { vFp->error = TRUE; return FALSE; } #endif return TRUE; } /****************************************************************************** * ComputeChecksumMD5. ******************************************************************************/ CDFstatus ComputeChecksumMD5 (vFp, size, signature) vFILE *vFp; long size; unsigned char signature[16]; { unsigned char buffer[BUFFSIZE]; struct MD5Context md5c; int jj = 0, readBytes; MD5Init(&md5c); if (fseek(vFp->fp, 0, vSEEK_SET) == EOF) return FALSE; while (jj < size) { if (jj+BUFFSIZE < size) readBytes = BUFFSIZE; else readBytes = size - jj; if (fread(buffer,1,readBytes,vFp->fp) != (size_t) readBytes) return FALSE; MD5Update(&md5c, buffer, (unsigned) readBytes); jj = jj + readBytes; } MD5Final(signature, &md5c); return TRUE; } /****************************************************************************** * ComputeChecksumMD5_64. ******************************************************************************/ CDFstatus ComputeChecksumMD5_64 (vFp, size, signature) vFILE *vFp; OFF_T size; unsigned char signature[16]; { unsigned char buffer[BUFFSIZE]; struct MD5Context md5c; OFF_T jj = 0; int readBytes; MD5Init(&md5c); #if defined(win32) && (_FILE_OFFSET_BITS == 64) if (FSEEK64(vFp->fh,(OFF_T) 0,vSEEK_SET) == EOF) return FALSE; #else if (FSEEK64(vFp->fp,(OFF_T) 0,vSEEK_SET) == EOF) return FALSE; #endif while (jj < size) { if (jj+BUFFSIZE < size) readBytes = BUFFSIZE; else readBytes = (int) (size - jj); #if defined(win32) && (_FILE_OFFSET_BITS == 64) if (FREAD64(vFp->fh,buffer,(unsigned int) readBytes) != (int) readBytes) return FALSE; #else if (FREAD64(buffer,1,readBytes,vFp->fp) != readBytes) return FALSE; #endif MD5Update(&md5c, buffer, (unsigned) readBytes); jj = jj + readBytes; } MD5Final(signature, &md5c); return TRUE; } /****************************************************************************** * GetChecksumMD5. ******************************************************************************/ CDFstatus GetChecksumMD5 (vFp, size, signature) vFILE *vFp; long size; unsigned char signature[16]; { if (fseek(vFp->fp,size,vSEEK_SET) == EOF) return FALSE; if (fread(signature,1,16,vFp->fp) != 16) return FALSE; return TRUE; } /****************************************************************************** * GetChecksumMD5_64. ******************************************************************************/ CDFstatus GetChecksumMD5_64 (vFp, size, signature) vFILE *vFp; OFF_T size; unsigned char *signature; { #if defined(win32) && (_FILE_OFFSET_BITS == 64) if (FSEEK64(vFp->fh,(OFF_T) size,vSEEK_SET) == EOF) return FALSE; if (FREAD64(vFp->fh,signature,16) != 16) return FALSE; #else if (FSEEK64(vFp->fp,(OFF_T) size,vSEEK_SET) == EOF) return FALSE; if (FREAD64(signature,1,16,vFp->fp) != 16) return FALSE; #endif return TRUE; } /****************************************************************************** * CDFVerifyChecksum. ******************************************************************************/ CDFstatus CDFVerifyChecksum (CDF) struct CDFstruct *CDF; { if (!CDF->largeFile) return VerifyChecksum (CDF); else return VerifyChecksum64 (CDF); } /****************************************************************************** * VerifyChecksum. ******************************************************************************/ CDFstatus VerifyChecksum (CDF) struct CDFstruct *CDF; { long GDRoffset, CPRoffset; Int32 CDRflags; long CCRsize, CPRsize, usedSize; CDFstatus pStatus = CDF_OK; unsigned char signature[16], csig[16]; if (!sX(ReadCDR(CDF->fp,V2_CDR_OFFSET, CDR_FLAGS,&CDRflags, CDR_GDROFFSET, &GDRoffset, CDR_NULL),&pStatus)) { return pStatus; } if (!BITSET(CDRflags,CDR_CHECKSUM_BIT)) return pStatus; if (CDF->uDotFp == NULL) { /************************************************************************** * A uncompressed CDF. **************************************************************************/ if (!sX(ReadGDR(CDF->dotFp,GDRoffset, GDR_EOF,&usedSize, GDR_NULL),&pStatus)) { return pStatus; } } else { /************************************************************************** * A compressed CDF. **************************************************************************/ if (!sX(ReadCCR(CDF->dotFp,V2_CCR_OFFSET, CCR_RECORDSIZE,&CCRsize, CCR_CPROFFSET, &CPRoffset, CCR_NULL),&pStatus)) { return pStatus; } if (!sX(ReadCPR(CDF->dotFp,CPRoffset, CPR_RECORDSIZE,&CPRsize, CPR_NULL),&pStatus)) { return pStatus; } usedSize = 8 + CCRsize + CPRsize; } if (BITSET(CDRflags,CDR_CHECKSUM_MD5_BIT)) { if (!sX(GetChecksumMD5(CDF->dotFp, usedSize, signature), &pStatus)) return pStatus; if (!sX(ComputeChecksumMD5(CDF->dotFp, usedSize, csig), &pStatus)) return pStatus; if (memcmp(signature, csig, 16) == 0) return CDF_OK; else return CHECKSUM_ERROR; } return pStatus; } /****************************************************************************** * VerifyChecksum64. ******************************************************************************/ CDFstatus VerifyChecksum64 (CDF) struct CDFstruct *CDF; { OFF_T GDRoffset, CPRoffset; Int32 CDRflags; OFF_T CCRsize, CPRsize, usedSize; CDFstatus pStatus = CDF_OK; unsigned char signature[16], csig[16]; if (!sX(ReadCDR64(CDF->fp,V3_CDR_OFFSET64, CDR_FLAGS,&CDRflags, CDR_GDROFFSET, &GDRoffset, CDR_NULL),&pStatus)) { return pStatus; } if (!BITSET(CDRflags,CDR_CHECKSUM_BIT)) return pStatus; if (CDF->uDotFp == NULL) { /************************************************************************** * A uncompressed CDF. **************************************************************************/ if (!sX(ReadGDR64(CDF->dotFp,GDRoffset, GDR_EOF,&usedSize, GDR_NULL),&pStatus)) { return pStatus; } } else { /************************************************************************** * A compressed CDF. **************************************************************************/ if (!sX(ReadCCR64(CDF->dotFp,V3_CCR_OFFSET64, CCR_RECORDSIZE,&CCRsize, CCR_CPROFFSET, &CPRoffset, CCR_NULL),&pStatus)) { return pStatus; } if (!sX(ReadCPR64(CDF->dotFp,CPRoffset, CPR_RECORDSIZE,&CPRsize, CPR_NULL),&pStatus)) { return pStatus; } usedSize = 8 + CCRsize + CPRsize; } if (BITSET(CDRflags,CDR_CHECKSUM_MD5_BIT)) { if (!sX(GetChecksumMD5_64(CDF->dotFp, usedSize, signature), &pStatus)) return pStatus; if (!sX(ComputeChecksumMD5_64(CDF->dotFp, usedSize, csig), &pStatus)) return pStatus; if (memcmp(signature, csig, 16) == 0) return CDF_OK; else return CHECKSUM_ERROR; } return pStatus; } /****************************************************************************** * CDFAddChecksum. ******************************************************************************/ CDFstatus CDFAddChecksum (CDF) struct CDFstruct *CDF; { if (!CDF->largeFile) return AddChecksum (CDF); else return AddChecksum64 (CDF); } /****************************************************************************** * AddChecksum. ******************************************************************************/ CDFstatus AddChecksum (CDF) struct CDFstruct *CDF; { long GDRoffset, CPRoffset; Int32 CDRflags; long CCRsize, CPRsize, usedSize; CDFstatus pStatus = CDF_OK; unsigned char signature[16]; if (!sX(ReadCDR(CDF->fp,V2_CDR_OFFSET, CDR_FLAGS,&CDRflags, CDR_GDROFFSET, &GDRoffset, CDR_NULL),&pStatus)) { return pStatus; } if (!BITSET(CDRflags,CDR_CHECKSUM_BIT)) return pStatus; if (CDF->uDotFp == NULL) { /************************************************************************** * A uncompressed CDF. **************************************************************************/ if (!sX(ReadGDR(CDF->dotFp,GDRoffset, GDR_EOF,&usedSize, GDR_NULL),&pStatus)) { return pStatus; } } else { /************************************************************************** * A compressed CDF. **************************************************************************/ if (!sX(ReadCCR(CDF->dotFp,V2_CCR_OFFSET, CCR_RECORDSIZE,&CCRsize, CCR_CPROFFSET, &CPRoffset, CCR_NULL),&pStatus)) { return pStatus; } if (!sX(ReadCPR(CDF->dotFp,CPRoffset, CPR_RECORDSIZE,&CPRsize, CPR_NULL),&pStatus)) { return pStatus; } usedSize = 8 + CCRsize + CPRsize; } if (BITSET(CDRflags,CDR_CHECKSUM_MD5_BIT)) { if (!sX(ComputeChecksumMD5(CDF->dotFp, usedSize, signature), &pStatus)) return pStatus; if (!sX(AddChecksumMD5(CDF->dotFp, usedSize, signature), &pStatus)) return pStatus; } return pStatus; } /****************************************************************************** * AddChecksum64. ******************************************************************************/ CDFstatus AddChecksum64 (CDF) struct CDFstruct *CDF; { OFF_T GDRoffset, CPRoffset; Int32 CDRflags; OFF_T CCRsize, CPRsize, usedSize; CDFstatus pStatus = CDF_OK; unsigned char signature[16]; if (!sX(ReadCDR64(CDF->fp,V3_CDR_OFFSET64, CDR_FLAGS,&CDRflags, CDR_GDROFFSET, &GDRoffset, CDR_NULL),&pStatus)) { return pStatus; } if (!BITSET(CDRflags,CDR_CHECKSUM_BIT)) return pStatus; if (CDF->uDotFp == NULL) { /************************************************************************** * A uncompressed CDF. **************************************************************************/ if (!sX(ReadGDR64(CDF->dotFp,GDRoffset, GDR_EOF,&usedSize, GDR_NULL),&pStatus)) { return pStatus; } } else { /************************************************************************** * A compressed CDF. **************************************************************************/ if (!sX(ReadCCR64(CDF->dotFp,V3_CCR_OFFSET64, CCR_RECORDSIZE,&CCRsize, CCR_CPROFFSET, &CPRoffset, CCR_NULL),&pStatus)) { return pStatus; } if (!sX(ReadCPR64(CDF->dotFp,CPRoffset, CPR_RECORDSIZE,&CPRsize, CPR_NULL),&pStatus)) { return pStatus; } usedSize = 8 + CCRsize + CPRsize; } if (BITSET(CDRflags,CDR_CHECKSUM_MD5_BIT)) { if (!sX(ComputeChecksumMD5_64(CDF->dotFp, usedSize, signature), &pStatus)) return pStatus; if (!sX(AddChecksumMD5_64(CDF->dotFp, usedSize, signature), &pStatus)) return pStatus; } return pStatus; }