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