1 /******************************************************************************
2 *
3 *  NSSDC/CDF                                        CDF `check sum' operations.
4 *
5 *  Version 1.0, 21-Mar-06, Hughes STX.
6 *
7 *  Modification history:
8 *
9 *   V1.0  21-Mar-06, M Liu      Original version.
10 ******************************************************************************/
11 
12 #include "cdflib.h"
13 #include "cdflib64.h"
14 #include "cdfmd5.h"
15 
16 #define BUFFSIZE 16384
17 
18 /******************************************************************************
19 * Local function prototypes.
20 ******************************************************************************/
21 CDFstatus AddChecksumMD5 PROTOARGs((vFILE *vFp, long size,
22                                     unsigned char *signature));
23 CDFstatus AddChecksumMD5_64 PROTOARGs((vFILE *vFp, OFF_T size,
24                                        unsigned char *signature));
25 CDFstatus ComputeChecksumMD5 PROTOARGs((vFILE *vFp, long size,
26                                         unsigned char *signature));
27 CDFstatus ComputeChecksumMD5_64 PROTOARGs((vFILE *vFp, OFF_T size,
28                                            unsigned char *signature));
29 CDFstatus GetChecksumMD5 PROTOARGs((vFILE *vFp, long size,
30                                     unsigned char *signature));
31 CDFstatus GetChecksumMD5_64 PROTOARGs((vFILE *vFp, OFF_T size,
32                                        unsigned char *signature));
33 CDFstatus AddChecksum PROTOARGs((struct CDFstruct *CDF));
34 CDFstatus AddChecksum64 PROTOARGs((struct CDFstruct *CDF));
35 CDFstatus VerifyChecksum PROTOARGs((struct CDFstruct *CDF));
36 CDFstatus VerifyChecksum64 PROTOARGs((struct CDFstruct *CDF));
37 
38 /******************************************************************************
39 * AddChecksumMD5.
40 ******************************************************************************/
41 
AddChecksumMD5(vFp,size,signature)42 CDFstatus AddChecksumMD5 (vFp, size, signature)
43 vFILE *vFp;
44 long  size;
45 unsigned char signature[16];
46 {
47 
48 #if defined(vms)
49   size_t lastBlk;
50   unsigned char buffer[512];
51   int i, j, inBlk, cross= 0;
52   inBlk = size % 512;
53   lastBlk = (size_t) 512 * (size / 512);
54   if (inBlk != 0) {
55     if (fseek(vFp->fp,lastBlk,SEEK_SET) == EOF) {
56       return FALSE;
57     }
58     for (i = 0; i < 512; i++) buffer[i] = 0;
59     if (fread(buffer,512,1,vFp->fp) != 1) {
60       return FALSE;
61     }
62     for (i = 0; i < 16; i++) {
63        j = inBlk + i;
64        if (j > 511) {
65          cross = i;
66          break;
67        }
68        buffer[j] = signature[i];
69     }
70     if (fseek(vFp->fp,lastBlk,SEEK_SET) == EOF) {
71       return FALSE;
72     }
73     if (fwrite(buffer,512,1,vFp->fp) != 1) {
74       return FALSE;
75     }
76 
77     if (cross > 0) {
78       for (i = 0; i < 512; i++) buffer[i] = 0;
79       j = 0;
80       for (i = cross; i < 16; i++) {
81          buffer[j] = signature[i];
82          j++;
83       }
84       if (fwrite(buffer,512,1,vFp->fp) != 1) {
85         return FALSE;
86       }
87     }
88   } else {
89     for (i = 16; i < 512; i++) buffer[i] = 0;
90     for (i = 0; i < 16; i++) buffer[i] = signature[i];
91     if (fseek(vFp->fp,size,SEEK_SET) == EOF) {
92       return FALSE;
93     }
94     if (fwrite(buffer,512,1,vFp->fp) != 1) {
95       return FALSE;
96     }
97   }
98 #else
99   if (fseek(vFp->fp,size,vSEEK_SET) == EOF) return FALSE;
100   if (fwrite(signature,1,16,vFp->fp) != 16) return FALSE;
101 #endif
102   if (fflush(vFp->fp) == EOF) {
103     vFp->error = TRUE;
104     return FALSE;
105   }
106   return TRUE;
107 }
108 
109 /******************************************************************************
110 * AddChecksumMD5_64.
111 ******************************************************************************/
112 
AddChecksumMD5_64(vFp,size,signature)113 CDFstatus AddChecksumMD5_64 (vFp, size, signature)
114 vFILE *vFp;
115 OFF_T  size;
116 unsigned char signature[16];
117 {
118 
119 #if defined(win32) && (_FILE_OFFSET_BITS == 64)
120   if (vFp->fh == 0) return FALSE;
121   if (FSEEK64(vFp->fh,(OFF_T) size,vSEEK_SET) == EOF) return FALSE;
122   if (FWRITE64(vFp->fh,signature,16) != 16) return FALSE;
123   if (FLUSH64(vFp->fh) == EOF) {
124     vFp->error = TRUE;
125     return FALSE;
126   }
127 #else
128   if (vFp->fp == NULL) return FALSE;
129 #if defined(vms)
130   OFF_T lastBlk;
131   unsigned char buffer[512];
132   int i, j, inBlk, cross= 0;
133   inBlk = size % 512;
134   lastBlk = (OFF_T) 512 * (size / 512);
135   if (inBlk != 0) {
136     if (FSEEK64(vFp->fp,lastBlk,SEEK_SET) == EOF) {
137       vFp->error = TRUE;
138       return FALSE;
139     }
140     for (i = 0; i < 512; i++) buffer[i] = 0;
141     if (FREAD64(buffer,512,1,vFp->fp) != 1) {
142       vFp->error = TRUE;
143       return FALSE;
144     }
145     for (i = 0; i < 16; i++) {
146        j = inBlk + i;
147        if (j > 511) {
148          cross = i;
149          break;
150        }
151        buffer[j] = signature[i];
152     }
153     if (FSEEK64(vFp->fp,lastBlk,SEEK_SET) == EOF) {
154       vFp->error = TRUE;
155       return FALSE;
156     }
157     if (FWRITE64(buffer,512,1,vFp->fp) != 1) {
158       vFp->error = TRUE;
159       return FALSE;
160     }
161 
162     if (cross > 0) {
163       for (i = 0; i < 512; i++) buffer[i] = 0;
164       j = 0;
165       for (i = cross; i < 16; i++) {
166          buffer[j] = signature[i];
167          j++;
168       }
169       if (FWRITE64(buffer,512,1,vFp->fp) != 1) {
170         vFp->error = TRUE;
171         return FALSE;
172       }
173     }
174   } else {
175     for (i = 16; i < 512; i++) buffer[i] = 0;
176     for (i = 0; i < 16; i++) buffer[i] = signature[i];
177     if (FSEEK64(vFp->fp,size,SEEK_SET) == EOF) {
178       vFp->error = TRUE;
179       return FALSE;
180     }
181     if (FWRITE64(buffer,512,1,vFp->fp) != 1) {
182       vFp->error = TRUE;
183       return FALSE;
184     }
185   }
186 #else
187   if (FSEEK64(vFp->fp,(OFF_T) size,vSEEK_SET) == EOF) return FALSE;
188   if (FWRITE64(signature,1,16,vFp->fp) != 16) return FALSE;
189 #endif
190   if (FLUSH64(vFp->fp) == EOF) {
191     vFp->error = TRUE;
192     return FALSE;
193   }
194 #endif
195   return TRUE;
196 }
197 
198 /******************************************************************************
199 * ComputeChecksumMD5.
200 ******************************************************************************/
201 
ComputeChecksumMD5(vFp,size,signature)202 CDFstatus ComputeChecksumMD5 (vFp, size, signature)
203 vFILE *vFp;
204 long  size;
205 unsigned char  signature[16];
206 {
207   unsigned char buffer[BUFFSIZE];
208   struct MD5Context md5c;
209   int jj = 0, readBytes;
210 
211   MD5Init(&md5c);
212   if (fseek(vFp->fp, 0, vSEEK_SET) == EOF) return FALSE;
213   while (jj < size) {
214      if (jj+BUFFSIZE < size) readBytes = BUFFSIZE;
215      else readBytes = size - jj;
216      if (fread(buffer,1,readBytes,vFp->fp) != (size_t) readBytes) return FALSE;
217      MD5Update(&md5c, buffer, (unsigned) readBytes);
218      jj = jj + readBytes;
219   }
220   MD5Final(signature, &md5c);
221   return TRUE;
222 
223 }
224 
225 /******************************************************************************
226 * ComputeChecksumMD5_64.
227 ******************************************************************************/
228 
ComputeChecksumMD5_64(vFp,size,signature)229 CDFstatus ComputeChecksumMD5_64 (vFp, size, signature)
230 vFILE *vFp;
231 OFF_T  size;
232 unsigned char  signature[16];
233 {
234   unsigned char buffer[BUFFSIZE];
235   struct MD5Context md5c;
236   OFF_T jj = 0;
237   int readBytes;
238 
239   MD5Init(&md5c);
240 #if defined(win32) && (_FILE_OFFSET_BITS == 64)
241      if (FSEEK64(vFp->fh,(OFF_T) 0,vSEEK_SET) == EOF) return FALSE;
242 #else
243      if (FSEEK64(vFp->fp,(OFF_T) 0,vSEEK_SET) == EOF) return FALSE;
244 #endif
245   while (jj < size) {
246      if (jj+BUFFSIZE < size) readBytes = BUFFSIZE;
247      else readBytes = (int) (size - jj);
248 #if defined(win32) && (_FILE_OFFSET_BITS == 64)
249      if (FREAD64(vFp->fh,buffer,(unsigned int) readBytes) != (int) readBytes)
250         return FALSE;
251 #else
252      if (FREAD64(buffer,1,readBytes,vFp->fp) != readBytes) return FALSE;
253 #endif
254      MD5Update(&md5c, buffer, (unsigned) readBytes);
255      jj = jj + readBytes;
256   }
257   MD5Final(signature, &md5c);
258   return TRUE;
259 }
260 
261 /******************************************************************************
262 * GetChecksumMD5.
263 ******************************************************************************/
264 
GetChecksumMD5(vFp,size,signature)265 CDFstatus GetChecksumMD5 (vFp, size, signature)
266 vFILE *vFp;
267 long  size;
268 unsigned char signature[16];
269 {
270 
271   if (fseek(vFp->fp,size,vSEEK_SET) == EOF) return FALSE;
272   if (fread(signature,1,16,vFp->fp) != 16) return FALSE;
273   return TRUE;
274 }
275 
276 /******************************************************************************
277 * GetChecksumMD5_64.
278 ******************************************************************************/
279 
GetChecksumMD5_64(vFp,size,signature)280 CDFstatus GetChecksumMD5_64 (vFp, size, signature)
281 vFILE *vFp;
282 OFF_T  size;
283 unsigned char *signature;
284 {
285 
286 #if defined(win32) && (_FILE_OFFSET_BITS == 64)
287   if (FSEEK64(vFp->fh,(OFF_T) size,vSEEK_SET) == EOF) return FALSE;
288   if (FREAD64(vFp->fh,signature,16) != 16) return FALSE;
289 #else
290   if (FSEEK64(vFp->fp,(OFF_T) size,vSEEK_SET) == EOF) return FALSE;
291   if (FREAD64(signature,1,16,vFp->fp) != 16) return FALSE;
292 #endif
293   return TRUE;
294 }
295 
296 /******************************************************************************
297 * CDFVerifyChecksum.
298 ******************************************************************************/
299 
CDFVerifyChecksum(CDF)300 CDFstatus CDFVerifyChecksum (CDF)
301 struct CDFstruct *CDF;
302 {
303 
304   if (!CDF->largeFile)
305     return VerifyChecksum (CDF);
306   else
307     return VerifyChecksum64 (CDF);
308 
309 }
310 
311 /******************************************************************************
312 * VerifyChecksum.
313 ******************************************************************************/
314 
VerifyChecksum(CDF)315 CDFstatus VerifyChecksum (CDF)
316 struct CDFstruct *CDF;
317 {
318   long GDRoffset, CPRoffset;
319   Int32 CDRflags;
320   long CCRsize, CPRsize, usedSize;
321   CDFstatus pStatus = CDF_OK;
322   unsigned char signature[16], csig[16];
323 
324   if (!sX(ReadCDR(CDF->fp,V2_CDR_OFFSET,
325                   CDR_FLAGS,&CDRflags,
326                   CDR_GDROFFSET, &GDRoffset,
327                   CDR_NULL),&pStatus)) {
328     return pStatus;
329   }
330 
331   if (!BITSET(CDRflags,CDR_CHECKSUM_BIT)) return pStatus;
332 
333   if (CDF->uDotFp == NULL) {
334     /**************************************************************************
335     * A uncompressed CDF.
336     **************************************************************************/
337     if (!sX(ReadGDR(CDF->dotFp,GDRoffset,
338                     GDR_EOF,&usedSize,
339                     GDR_NULL),&pStatus)) {
340       return pStatus;
341     }
342   } else {
343     /**************************************************************************
344     * A compressed CDF.
345     **************************************************************************/
346     if (!sX(ReadCCR(CDF->dotFp,V2_CCR_OFFSET,
347                     CCR_RECORDSIZE,&CCRsize,
348                     CCR_CPROFFSET, &CPRoffset,
349                     CCR_NULL),&pStatus)) {
350       return pStatus;
351     }
352     if (!sX(ReadCPR(CDF->dotFp,CPRoffset,
353                     CPR_RECORDSIZE,&CPRsize,
354                     CPR_NULL),&pStatus)) {
355       return pStatus;
356     }
357     usedSize = 8 + CCRsize + CPRsize;
358   }
359 
360   if (BITSET(CDRflags,CDR_CHECKSUM_MD5_BIT)) {
361     if (!sX(GetChecksumMD5(CDF->dotFp, usedSize, signature),
362         &pStatus)) return pStatus;
363     if (!sX(ComputeChecksumMD5(CDF->dotFp, usedSize, csig),
364         &pStatus)) return pStatus;
365     if (memcmp(signature, csig, 16) == 0) return CDF_OK;
366     else return CHECKSUM_ERROR;
367   }
368   return pStatus;
369 }
370 
371 /******************************************************************************
372 * VerifyChecksum64.
373 ******************************************************************************/
374 
VerifyChecksum64(CDF)375 CDFstatus VerifyChecksum64 (CDF)
376 struct CDFstruct *CDF;
377 {
378   OFF_T GDRoffset, CPRoffset;
379   Int32 CDRflags;
380   OFF_T CCRsize, CPRsize, usedSize;
381   CDFstatus pStatus = CDF_OK;
382   unsigned char signature[16], csig[16];
383 
384   if (!sX(ReadCDR64(CDF->fp,V3_CDR_OFFSET64,
385                     CDR_FLAGS,&CDRflags,
386                     CDR_GDROFFSET, &GDRoffset,
387                     CDR_NULL),&pStatus)) {
388     return pStatus;
389   }
390   if (!BITSET(CDRflags,CDR_CHECKSUM_BIT)) return pStatus;
391   if (CDF->uDotFp == NULL) {
392     /**************************************************************************
393     * A uncompressed CDF.
394     **************************************************************************/
395     if (!sX(ReadGDR64(CDF->dotFp,GDRoffset,
396                       GDR_EOF,&usedSize,
397                       GDR_NULL),&pStatus)) {
398       return pStatus;
399     }
400   } else {
401     /**************************************************************************
402     * A compressed CDF.
403     **************************************************************************/
404     if (!sX(ReadCCR64(CDF->dotFp,V3_CCR_OFFSET64,
405                       CCR_RECORDSIZE,&CCRsize,
406                       CCR_CPROFFSET, &CPRoffset,
407                       CCR_NULL),&pStatus)) {
408       return pStatus;
409     }
410     if (!sX(ReadCPR64(CDF->dotFp,CPRoffset,
411                       CPR_RECORDSIZE,&CPRsize,
412                       CPR_NULL),&pStatus)) {
413       return pStatus;
414     }
415     usedSize = 8 + CCRsize + CPRsize;
416   }
417 
418   if (BITSET(CDRflags,CDR_CHECKSUM_MD5_BIT)) {
419     if (!sX(GetChecksumMD5_64(CDF->dotFp, usedSize, signature),
420         &pStatus)) return pStatus;
421     if (!sX(ComputeChecksumMD5_64(CDF->dotFp, usedSize, csig),
422         &pStatus)) return pStatus;
423     if (memcmp(signature, csig, 16) == 0) return CDF_OK;
424     else return CHECKSUM_ERROR;
425   }
426   return pStatus;
427 }
428 
429 /******************************************************************************
430 * CDFAddChecksum.
431 ******************************************************************************/
432 
CDFAddChecksum(CDF)433 CDFstatus CDFAddChecksum (CDF)
434 struct CDFstruct *CDF;
435 {
436   if (!CDF->largeFile)
437     return AddChecksum (CDF);
438   else
439     return AddChecksum64 (CDF);
440 }
441 
442 /******************************************************************************
443 * AddChecksum.
444 ******************************************************************************/
445 
AddChecksum(CDF)446 CDFstatus AddChecksum (CDF)
447 struct CDFstruct *CDF;
448 {
449   long GDRoffset, CPRoffset;
450   Int32 CDRflags;
451   long CCRsize, CPRsize, usedSize;
452   CDFstatus pStatus = CDF_OK;
453   unsigned char signature[16];
454 
455   if (!sX(ReadCDR(CDF->fp,V2_CDR_OFFSET,
456                   CDR_FLAGS,&CDRflags,
457                   CDR_GDROFFSET, &GDRoffset,
458                   CDR_NULL),&pStatus)) {
459     return pStatus;
460   }
461 
462   if (!BITSET(CDRflags,CDR_CHECKSUM_BIT)) return pStatus;
463 
464   if (CDF->uDotFp == NULL) {
465     /**************************************************************************
466     * A uncompressed CDF.
467     **************************************************************************/
468     if (!sX(ReadGDR(CDF->dotFp,GDRoffset,
469                     GDR_EOF,&usedSize,
470                     GDR_NULL),&pStatus)) {
471       return pStatus;
472     }
473   } else {
474     /**************************************************************************
475     * A compressed CDF.
476     **************************************************************************/
477     if (!sX(ReadCCR(CDF->dotFp,V2_CCR_OFFSET,
478                     CCR_RECORDSIZE,&CCRsize,
479                     CCR_CPROFFSET, &CPRoffset,
480                     CCR_NULL),&pStatus)) {
481       return pStatus;
482     }
483     if (!sX(ReadCPR(CDF->dotFp,CPRoffset,
484                     CPR_RECORDSIZE,&CPRsize,
485                     CPR_NULL),&pStatus)) {
486       return pStatus;
487     }
488     usedSize = 8 + CCRsize + CPRsize;
489   }
490 
491   if (BITSET(CDRflags,CDR_CHECKSUM_MD5_BIT)) {
492     if (!sX(ComputeChecksumMD5(CDF->dotFp, usedSize, signature),
493         &pStatus)) return pStatus;
494     if (!sX(AddChecksumMD5(CDF->dotFp, usedSize, signature),
495         &pStatus)) return pStatus;
496   }
497   return pStatus;
498 }
499 
500 
501 /******************************************************************************
502 * AddChecksum64.
503 ******************************************************************************/
504 
AddChecksum64(CDF)505 CDFstatus AddChecksum64 (CDF)
506 struct CDFstruct *CDF;
507 {
508   OFF_T GDRoffset, CPRoffset;
509   Int32 CDRflags;
510   OFF_T CCRsize, CPRsize, usedSize;
511   CDFstatus pStatus = CDF_OK;
512   unsigned char signature[16];
513 
514   if (!sX(ReadCDR64(CDF->fp,V3_CDR_OFFSET64,
515                     CDR_FLAGS,&CDRflags,
516                     CDR_GDROFFSET, &GDRoffset,
517                     CDR_NULL),&pStatus)) {
518     return pStatus;
519   }
520 
521   if (!BITSET(CDRflags,CDR_CHECKSUM_BIT)) return pStatus;
522 
523   if (CDF->uDotFp == NULL) {
524     /**************************************************************************
525     * A uncompressed CDF.
526     **************************************************************************/
527     if (!sX(ReadGDR64(CDF->dotFp,GDRoffset,
528                       GDR_EOF,&usedSize,
529                       GDR_NULL),&pStatus)) {
530       return pStatus;
531     }
532   } else {
533     /**************************************************************************
534     * A compressed CDF.
535     **************************************************************************/
536     if (!sX(ReadCCR64(CDF->dotFp,V3_CCR_OFFSET64,
537                       CCR_RECORDSIZE,&CCRsize,
538                       CCR_CPROFFSET, &CPRoffset,
539                       CCR_NULL),&pStatus)) {
540       return pStatus;
541     }
542     if (!sX(ReadCPR64(CDF->dotFp,CPRoffset,
543                       CPR_RECORDSIZE,&CPRsize,
544                       CPR_NULL),&pStatus)) {
545       return pStatus;
546     }
547     usedSize = 8 + CCRsize + CPRsize;
548   }
549 
550   if (BITSET(CDRflags,CDR_CHECKSUM_MD5_BIT)) {
551     if (!sX(ComputeChecksumMD5_64(CDF->dotFp, usedSize, signature),
552         &pStatus)) return pStatus;
553     if (!sX(AddChecksumMD5_64(CDF->dotFp, usedSize, signature),
554         &pStatus)) return pStatus;
555   }
556   return pStatus;
557 }
558 
559