static bool test_ctr_op(const struct encrypt_desc *encrypt_desc, const char *description, int encrypt, PK11SymKey *sym_key, const char *encoded_cb, const char *output_cb, const char *input_name, const char *input, const char *output_name, const char *output) { const char *op = encrypt ? "encrypt" : "decrypt"; bool ok = TRUE; chunk_t cb = decode_to_chunk("input counter-block: ", encoded_cb); chunk_t tmp = decode_to_chunk(input_name, input); chunk_t expected_output = decode_to_chunk(output_name, output); chunk_t expected_cb = decode_to_chunk("expected counter-block: ", output_cb); /* do_crypt modifies the data and IV in place. */ encrypt_desc->encrypt_ops->do_crypt(encrypt_desc, tmp.ptr, tmp.len, sym_key, cb.ptr, encrypt); if (!verify_chunk(op, expected_output, tmp)) { DBG(DBG_CRYPT, DBG_log("test_ctr_op: %s: %s: output does not match", description, op)); ok = FALSE; } if (!verify_chunk("counter-block", expected_cb, cb)) { DBG(DBG_CRYPT, DBG_log("test_ctr_op: %s: %s: counter-block does not match", description, op)); ok = FALSE; } freeanychunk(cb); freeanychunk(expected_cb); freeanychunk(tmp); freeanychunk(expected_output); return ok; }
int main (int argc, char const *argv[]) { UNUSED_ARG(argc); UNUSED_ARG(argv); unsigned i; memory_pool * mp = mempool_new(POOL_ENTRIES, POOL_ENTRY_SIZE); void * chunks[POOL_ENTRIES]; // Allocate all then free all for(i = 0; i < POOL_ENTRIES; ++i) { //Allocate chunk chunks[i] = mempool_alloc(mp); //Write into it write_chunk(chunks[i], (char)(i % 255)); } for(i = 0; i < POOL_ENTRIES; ++i) { //Verify contents verify_chunk(chunks[i], (char)(i % 255)); //Release mempool_free(mp, chunks[i]); chunks[i] = NULL; } // Allocate all then free by using is_mempool_exhaused for(i = 0; is_mempool_exhaused(mp) == false; ++i) { //Allocate chunk chunks[i] = mempool_alloc(mp); //Write into it write_chunk(chunks[i], (char)(i % 255)); } assert(i == POOL_ENTRIES); for(i = 0; i < POOL_ENTRIES; ++i) { //Verify contents verify_chunk(chunks[i], (char)(i % 255)); //Release mempool_free(mp, chunks[i]); chunks[i] = NULL; } printf("TEST SUCCESSFUL!\n"); return 0; }
unsigned char *lookup_chunk(struct db *db, const unsigned char *digest) { struct index *root = db->root; struct index *leaf; uint32_t hash = *(uint32_t *)digest; int i, leaf_nr; unsigned char *chunk; /* XXX: this may need to become a binary search */ for (leaf_nr = 1; leaf_nr < be32toh(root[0].hash); leaf_nr ++) if (hash < be32toh(root[leaf_nr].hash)) break; TRACE("leaf_nr=%d chunk_nr=%u hash=%x\n", leaf_nr, be32toh(root[leaf_nr-1].chunk_nr), be32toh(root[leaf_nr-1].hash)); leaf = map_chunk(db, be32toh(root[leaf_nr - 1].chunk_nr)); if (IS_ERR(leaf)) return (void *)leaf; for (i = 0; i < MAX_INDEX; i ++) { if (be32toh(leaf[i].chunk_nr) == INVALID_CHUNK_NR) break; if (hash < be32toh(leaf[i].hash)) break; if (hash == be32toh(leaf[i].hash)) { chunk = map_chunk(db, be32toh(leaf[i].chunk_nr)); if (IS_ERR(chunk)) goto out; if (verify_chunk(chunk, digest)) goto out; unmap_chunk(chunk); } } chunk = NULL; out: unmap_chunk(leaf); return chunk; }
static int fetch_chunk(unsigned char *chunk, const unsigned char *digest, void *db_info) { const char *fetch_cmd = db_info; char chunk_name[CHUNK_DIGEST_STRLEN+1]; int err; int fd[2]; int pid; int len; int n; if (!fetch_cmd) return -EIO; __digest_string(digest, chunk_name); TRACE("chunk=%s using %s\n", chunk_name, fetch_cmd); err = pipe(fd); if (err) { ERROR("pipe: %s\n", strerror(errno)); return -EIO; } pid = fork(); if (pid < 0) { ERROR("fork: %s\n", strerror(errno)); close(fd[0]); close(fd[1]); return -EIO; } if (pid) { int status; close(fd[1]); for (len = 0; len < CHUNK_SIZE; ) { n = read(fd[0], chunk + len, CHUNK_SIZE - len); if (n < 0) { if (errno == EINTR) continue; WARNING("read: %s\n", strerror(errno)); err = -errno; close(fd[1]); kill(pid, 9); waitpid(pid, NULL, 0); return -EIO; } if (!n) break; len += n; } close(fd[0]); /* * Don't worry about return values from waitpid(), * as the chunk is already fetched. */ waitpid(pid, &status, 0); if (!verify_chunk(chunk, digest)) { ERROR("Chunk failed verification\n"); return -EIO; } TRACE("len=%d", len); return len; } close(fd[0]); err = dup2(fd[1], STDOUT_FILENO); if (err < 0) { err = errno; ERROR("stdout redirection failed: %s\n", strerror(err)); exit(-errno); } if (zunkfs_log_fd) { err = dup2(fileno(zunkfs_log_fd), STDERR_FILENO); if (err < 0) { err = errno; ERROR("stderr redirection failed: %s\n", strerror(err)); exit(-errno); } } execl(fetch_cmd, fetch_cmd, chunk_name, NULL); err = errno; ERROR("\"%s %s\" failed: %s\n", fetch_cmd, chunk_name, strerror(err)); exit(-err); /* prevent compiler warnings */ return 0; }
/* * read_chunk: reads the chunk_buf from the device. The number of read * operations are based on the parameters read_end, offset, and chunksize. */ int read_chunks(int fd, unsigned long long offset, unsigned long long read_end, char *chunk_buf, size_t chunksize, const time_t time_st, const ino_t inode_st, const char *file) { unsigned long long stride, count = 0; if (ioctl(fd, BLKFLSBUF, 0) < 0 && verbose) fprintf(stderr, "%s: ioctl BLKFLSBUF failed: %s (ignoring)\n", progname, strerror(errno)); stride = full ? chunksize : (ONE_GB - chunksize); for (offset = offset & ~(chunksize - 1); offset < read_end; offset += stride) { ssize_t nread; if (lseek64(fd, offset, SEEK_SET) == -1) { fprintf(stderr, "\n%s: lseek64(%llu) failed: %s\n", progname, offset, strerror(errno)); return 1; } if (offset + chunksize > read_end) chunksize = read_end - offset; if (!full && offset > chunksize) { nread = read(fd, chunk_buf, chunksize); if (nread < 0) { fprintf(stderr,"\n%s: read %s@%llu+%zi failed: " "%s\n", progname, file, offset, chunksize, strerror(errno)); error_count++; return 1; } if (nread < chunksize) { fprintf(stderr, "\n%s: read %s@%llu+%zi short: " "%zi read\n", progname, file, offset, chunksize, nread); error_count++; } if (verify_chunk(chunk_buf, nread, offset, time_st, inode_st, file) != 0) return 1; offset += chunksize; count += chunksize; /* Need to reset position after read error */ if (nread < chunksize && lseek64(fd, offset, SEEK_SET) == -1) { fprintf(stderr, "\n%s: lseek64(%s@%llu) failed: %s\n", progname, file, offset,strerror(errno)); return 1; } if (offset + chunksize >= read_end) chunksize = read_end - offset; } nread = read(fd, chunk_buf, chunksize); if (nread < 0) { fprintf(stderr, "\n%s: read failed: %s\n", progname, strerror(errno)); error_count++; return 1; } if (nread < chunksize) { fprintf(stderr, "\n%s: read %s@%llu+%zi short: " "%zi read\n", progname, file, offset, chunksize, nread); error_count++; } if (verify_chunk(chunk_buf, nread, offset, time_st, inode_st, file) != 0) return 1; count += chunksize; if (verbose > 1) show_rate("read", offset, &count); } if (verbose > 1) { show_rate("read", offset, &count); printf("\nread complete\n"); } return 0; }
static int do_o_direct_reads(void) { int fd, ret; unsigned int i; void *buf = 0; time_t cur_time, end_time; ret = posix_memalign(&buf, page_size, page_size); if (ret) { printf("do_o_direct_reads: posix_memalign returned %d\n", ret); goto done; } fd = open(temp_file, O_RDONLY | O_DIRECT); if (fd < 0) { ret = errno; printf("do_o_direct_reads: error opening fd: %d\n", ret); goto free_buf; } // read the first chunk and see if it looks OK ret = do_read(fd, buf, page_size); if (ret) goto close_fd; ret = verify_chunk((struct chunk*)buf, 0); if (ret) goto close_fd; // read some random chunks and see how they look cur_time = time(NULL); end_time = cur_time + g_duration; i = 0; do { time_t next_time; uint64_t offset; int page; unsigned int seed; seed = i++; page = rand_r(&seed) % g_num_pages; offset = page; offset *= page_size; if (lseek64(fd, offset, SEEK_SET) == -1) { int err = errno; printf("lseek64(%" PRId64 ") failed: error %d (%s)\n", offset, err, strerror(err)); goto close_fd; } ret = do_read(fd, buf, page_size); if (ret) goto close_fd; ret = verify_chunk((struct chunk*)buf, offset); if (ret) goto close_fd; next_time = time(NULL); if (next_time > cur_time) { printf("."); } cur_time = next_time; } while (time(NULL) < end_time); printf("\ndo_o_direct_reads: SUCCESS\n"); close_fd: TEMP_FAILURE_RETRY(close(fd)); free_buf: free(buf); done: return ret; }