2 * Copyright (c) 2009 - Secure Endpoints Inc.
4 * Author: Asanka Herath <asanka@secure-endpoints.com>
12 #define BLOCKSIZE 1024
15 typedef __int64 offset_t;
17 HCRYPTPROV h_prov = 0;
21 const char * filename = "";
23 BOOL show_offsets = FALSE;
25 typedef struct hash_data {
30 #define ROUNDUP(x, align) (((((x) - 1) / (align)) + 1) * (align))
32 void dump_hex(BYTE * buffer, int cb)
34 static const char *htable[] = {
35 "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"
39 for (i=0; i < cb; i++) {
41 fprintf(stderr, "\n%08X : ", i);
44 fprintf(stderr, "%s%s",
45 htable[(buffer[i] >> 4) & 0xf],
46 htable[(buffer[i] & 0xf)]);
54 fprintf(stderr, "\n");
57 #define CCall(f) if (!f) goto done;
59 BOOL init_test_data(void)
61 return CryptAcquireContext(&h_prov, NULL, MS_DEF_PROV, PROV_RSA_FULL,
62 CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
65 void exit_test_data(void)
68 CryptReleaseContext(h_prov, 0);
72 BOOL generate_test_data_block(offset_t offset, DWORD param, BYTE buffer[BLOCKSIZE])
74 HCRYPTHASH h_hash = 0;
80 ZeroMemory(&d, sizeof(d));
85 CCall(CryptCreateHash(h_prov, CALG_SHA1, 0, 0, &h_hash));
86 CCall(CryptHashData(h_hash, (BYTE *) &d, sizeof(d), 0));
87 CCall(CryptDeriveKey(h_prov, CALG_RC4, h_hash, CRYPT_NO_SALT, &h_key));
89 ZeroMemory(buffer, BLOCKSIZE);
91 CCall(CryptEncrypt(h_key, 0, TRUE, 0, buffer, &cb_data, cb_data));
93 //dump_hex(buffer, 32);
99 CryptDestroyHash(h_hash);
101 CryptDestroyKey(h_key);
106 BOOL verify_test_data_block(offset_t offset, DWORD param, BYTE buffer[BLOCKSIZE])
108 BYTE expected[BLOCKSIZE];
110 if (!generate_test_data_block(offset, param, expected)) {
113 if (!memcmp(expected, buffer, BLOCKSIZE)) {
114 if (param > 0 && show_offsets)
115 printf("... [%I64d]\n", offset, param);
122 typedef struct bitmap {
129 #define BMAGIC 0xbeefface
131 #define NBITMAPBYTES(n) (ROUNDUP((n)/BLOCKSIZE, 8)/8)
132 #define BITMAPSIZE(n) (sizeof(bitmap) + NBITMAPBYTES(n) - 1)
133 #define FILESIZE(n) (DATAOFFSET(n) + (n))
134 #define DATAOFFSET(n) ROUNDUP(BITMAPSIZE(n), BLOCKSIZE)
136 bitmap * allocbits(offset_t N)
140 b = malloc(BITMAPSIZE(N));
144 memset(b, 0, BITMAPSIZE(N));
148 b->o_data = DATAOFFSET(N);
153 void freebits(bitmap * b)
159 void setbit(bitmap * b, offset_t o)
161 if (o < b->o_data || o >= b->o_data + b->length || (o % BLOCKSIZE) != 0) {
162 fprintf(stderr, "Internal error. Invalid offset\n");
166 o = (o - b->o_data) / BLOCKSIZE;
168 b->bits[o / 8] |= (1 << (o & 7));
171 BOOL getbit(bitmap * b, offset_t o)
173 if (o < b->o_data || o >= b->o_data + b->length || (o % BLOCKSIZE) != 0) {
174 fprintf(stderr, "Internal error. Invalid offset\n");
178 o = (o - b->o_data) / BLOCKSIZE;
180 return !!(b->bits[o / 8] & (1 << (o & 7)));
183 BOOL write_bitmap(HANDLE h, bitmap * b)
188 BOOL success = FALSE;
190 ZeroMemory(&ov, sizeof(ov));
192 b_size = BITMAPSIZE(b->length);
196 if (!SetFilePointerEx(h, li, &li, FILE_BEGIN)) {
197 fprintf(stderr, "Can't set file pointer. GLE=%d\n", GetLastError());
201 for (o = 0; o < b_size; o += BLOCKSIZE) {
202 BYTE buffer[BLOCKSIZE];
205 if (o + BLOCKSIZE <= b_size) {
206 memcpy(buffer, ((BYTE *) b) + o, BLOCKSIZE);
208 memcpy(buffer, ((BYTE *) b) + o, (b_size - o));
209 memset(buffer + (b_size - o), 0, BLOCKSIZE - (b_size - o));
213 ov.Offset = li.LowPart;
214 ov.OffsetHigh = li.HighPart;
216 if (!LockFileEx(h, LOCKFILE_EXCLUSIVE_LOCK, 0, BLOCKSIZE, 0, &ov)) {
217 fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
221 if (!WriteFile(h, buffer, BLOCKSIZE, &n_written, NULL) || n_written != BLOCKSIZE) {
222 fprintf(stderr, "Can't write data. GLE=%d\n", GetLastError());
226 if (!UnlockFileEx(h, 0, BLOCKSIZE, 0, &ov)) {
227 fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
233 if (!SetFilePointerEx(h, li, &li, FILE_CURRENT)) {
234 fprintf(stderr, "Can't set file pointer. GLE=%d\n", GetLastError());
238 if (li.QuadPart != b->o_data) {
239 fprintf(stderr, "Current file pointer is not at start of data.\n");
250 bitmap* read_bitmap(HANDLE h)
254 bitmap * bfile = NULL;
255 bitmap * bprep = NULL;
257 BYTE buffer[BLOCKSIZE];
261 ZeroMemory(&ov, sizeof(ov));
265 if (!SetFilePointerEx(h, li, &li, FILE_BEGIN)) {
266 fprintf(stderr, "Can't set file pointer. GLE=%d\n", GetLastError());
273 if (!LockFileEx(h, 0, 0, BLOCKSIZE, 0, &ov)) {
274 fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
278 if (!ReadFile(h, buffer, BLOCKSIZE, &n_read, NULL) || n_read != BLOCKSIZE) {
279 fprintf(stderr, "Can't read data. GLE=%d\n", GetLastError());
283 if (!UnlockFileEx(h, 0, BLOCKSIZE, 0, &ov)) {
284 fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
288 bfile = (bitmap *)buffer;
290 if (bfile->magic != BMAGIC) {
291 fprintf(stderr, "Corrupt data. Magic number is invalid\n");
295 if (!GetFileSizeEx(h, &li)) {
296 fprintf(stderr, "Can't get file size. GLE=%d\n", GetLastError());
300 if (li.QuadPart != FILESIZE(bfile->length)) {
301 fprintf(stderr, "Corrupt data. Invalid file size.\n");
305 if (bfile->o_data != DATAOFFSET(bfile->length)) {
306 fprintf(stderr, "Corrupt data. Invalid data offset.\n");
310 bprep = allocbits(bfile->length);
313 fprintf(stderr, "Can't allocate memory for bitmap\n");
317 memcpy(bprep, bfile, __min(BITMAPSIZE(bfile->length), BLOCKSIZE));
319 for (o = BLOCKSIZE; o < BITMAPSIZE(bprep->length); o += BLOCKSIZE) {
321 ov.Offset = li.LowPart;
322 ov.OffsetHigh = li.HighPart;
324 if (!LockFileEx(h, 0, 0, BLOCKSIZE, 0, &ov)) {
325 fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
329 if (!ReadFile(h, buffer, BLOCKSIZE, &n_read, NULL) || n_read != BLOCKSIZE) {
330 fprintf(stderr, "Can't read data. GLE=%d\n", GetLastError());
334 if (!UnlockFileEx(h, 0, BLOCKSIZE, 0, &ov)) {
335 fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
339 memcpy(((BYTE *) bprep) + o, buffer, __min(BITMAPSIZE(bprep->length) - o, BLOCKSIZE));
343 if (!SetFilePointerEx(h, li, &li, FILE_CURRENT)) {
344 fprintf(stderr, "Can't set file pointer. GLE=%d\n", GetLastError());
348 if (li.QuadPart != bprep->o_data) {
349 fprintf(stderr, "Current file pointer not at start of data.\n");
356 if (brv == NULL && bprep != NULL) {
362 int do_verify_test(void)
364 HANDLE h_file = NULL;
371 printf("Verifying test data file [%s]\n", filename);
373 h_file = CreateFile(filename, GENERIC_READ, FILE_SHARE_WRITE, NULL,
374 OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
375 if (h_file == INVALID_HANDLE_VALUE) {
376 fprintf(stderr, "Can't open file [%s] GLE=%d\n", filename, GetLastError());
380 b = read_bitmap(h_file);
388 printf("File size N = %I64d\n", N);
390 if (!init_test_data()) {
391 fprintf(stderr, "Initialize crypto. GLE=%d\n", GetLastError());
395 printf("Verifying data ... \n");
397 ZeroMemory(&ov, sizeof(ov));
399 for (offset = b->o_data; offset < b->o_data+N; offset += BLOCKSIZE) {
400 BYTE buffer[BLOCKSIZE];
403 li.QuadPart = offset;
404 ov.Offset = li.LowPart;
405 ov.OffsetHigh = li.HighPart;
407 if (!LockFileEx(h_file, 0, 0, BLOCKSIZE, 0, &ov)) {
409 fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
413 if (!ReadFile(h_file, buffer, BLOCKSIZE, &n_read, NULL) || n_read != BLOCKSIZE) {
415 fprintf(stderr, "Can't read data. GLE=%d\n", GetLastError());
419 if (!verify_test_data_block(offset, ((getbit(b, offset))? 1 : 0), buffer)) {
420 printf("VERIFY FAILED\n");
421 fprintf(stderr, "Verification failed at offset %I64d\n", offset);
425 if (!UnlockFileEx(h_file, 0, BLOCKSIZE, 0, &ov)) {
427 fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
432 printf("Verify succeeded!\n");
448 int do_write_test(void)
450 HANDLE h_file = NULL;
456 printf("Generating test data file [%s]\n", filename);
458 N = (((N - 1)/BLOCKSIZE) + 1) * BLOCKSIZE;
459 M = (((M - 1)/BLOCKSIZE) + 1) * BLOCKSIZE;
461 printf("Using N = %I64d and M = %I64d\n", N, M);
463 h_file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
464 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, NULL);
465 if (h_file == INVALID_HANDLE_VALUE) {
466 fprintf(stderr, "Can't create file [%s] GLE=%d\n", filename, GetLastError());
472 fprintf(stderr, "Can't allocate bitmap.\n");
476 if (!init_test_data()) {
477 fprintf(stderr, "Initialize crypto. GLE=%d\n", GetLastError());
481 printf("Phase 1: Generating test data ... ");
483 if (!write_bitmap(h_file, b)) {
487 ZeroMemory(&ov, sizeof(ov));
489 for (offset = b->o_data; offset < b->o_data + N; offset += BLOCKSIZE) {
490 BYTE buffer[BLOCKSIZE];
494 if (!generate_test_data_block(offset, 0, buffer)) {
496 fprintf(stderr, "Can't generate test data. GLE=%d\n", GetLastError());
500 li.QuadPart = offset;
501 ov.Offset = li.LowPart;
502 ov.OffsetHigh = li.HighPart;
504 if (!LockFileEx(h_file, LOCKFILE_EXCLUSIVE_LOCK, 0, BLOCKSIZE, 0, &ov)) {
506 fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
510 if (!WriteFile(h_file, buffer, BLOCKSIZE, &n_written, NULL) || n_written != BLOCKSIZE) {
512 fprintf(stderr, "Can't write data. GLE=%d\n", GetLastError());
516 if (!UnlockFileEx(h_file, 0, BLOCKSIZE, 0, &ov)) {
518 fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
525 if (!FlushFileBuffers(h_file)) {
526 fprintf(stderr, "Can't flush file. GLE=%d\n", GetLastError());
530 printf("Phase 2: Overwriting test data ... \n");
532 for (offset = 0; offset < M; offset += BLOCKSIZE) {
534 BYTE buffer[BLOCKSIZE];
538 if (!CryptGenRandom(h_prov, sizeof(orandom), (BYTE *) &orandom)) {
540 fprintf(stderr, "Can't generate random number. GLE=%d\n", GetLastError());
546 orandom = ((orandom % N) / BLOCKSIZE) * BLOCKSIZE;
547 orandom += b->o_data;
550 printf("... [%I64d]\n", orandom);
552 if (!generate_test_data_block(orandom, 1, buffer)) {
554 fprintf(stderr, "Can't generate test data. GLE=%d\n", GetLastError());
558 li.QuadPart = orandom;
559 ov.Offset = li.LowPart;
560 ov.OffsetHigh = li.HighPart;
562 if (!LockFileEx(h_file, LOCKFILE_EXCLUSIVE_LOCK, 0, BLOCKSIZE, 0, &ov)) {
564 fprintf(stderr, "Can't lock file. GLE=%d\n", GetLastError());
568 if (!SetFilePointerEx(h_file, li, NULL, FILE_BEGIN)) {
570 fprintf(stderr, "Can't set file pointer. GLE=%d\n", GetLastError());
574 if (!WriteFile(h_file, buffer, BLOCKSIZE, &n_written, NULL) || n_written != BLOCKSIZE) {
576 fprintf(stderr, "Can't write data. GLE=%d\n", GetLastError());
580 if (!UnlockFileEx(h_file, 0, BLOCKSIZE, 0, &ov)) {
582 fprintf(stderr, "Can't unlock file. GLE=%d\n", GetLastError());
589 if (!write_bitmap(h_file, b)) {
609 BOOL show_usage(const char * fn)
612 "%s : Generate or verify test data file.\n"
614 "Usage: %s [-r <filename> | -w <N> <M> <filename>]\n"
616 " -w <N> <M> <filename> :\n"
617 " First writes N bytes of random data into <filename> and then\n"
618 " overwrites M bytes with different random data.\n"
620 " -r <filename> : \n"
621 " Verify the contents of <filename>. Verification succeeds if\n"
622 " the contents of <filename> was generated using the -w option\n",
627 BOOL parse_cmdline(int argc, char ** argv)
630 if (strcmp(argv[1], "-r"))
631 return show_usage(argv[0]);
640 if (strcmp(argv[1], "-w"))
641 return show_usage(argv[0]);
645 return show_usage(argv[0]);
648 return show_usage(argv[0]);
653 return show_usage(argv[0]);
659 return do_verify_test();
661 return do_write_test();
664 int main(int argc, char ** argv)
666 if (!parse_cmdline(argc, argv))