int read_cache(void) { int fd, i; struct stat st; unsigned long size, offset; void *map; struct cache_header *hdr; errno = EBUSY; if (active_cache) return error("more than one cachefile"); errno = ENOENT; sha1_file_directory = getenv(DB_ENVIRONMENT); if (!sha1_file_directory) sha1_file_directory = DEFAULT_DB_ENVIRONMENT; if (access(sha1_file_directory, X_OK) < 0) return error("no access to SHA1 file directory"); fd = open(get_index_file(), O_RDONLY); if (fd < 0) return (errno == ENOENT) ? 0 : error("open failed"); size = 0; // avoid gcc warning map = (void *)-1; if (!fstat(fd, &st)) { size = st.st_size; errno = EINVAL; if (size >= sizeof(struct cache_header) + 20) map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); } close(fd); if (-1 == (int)(long)map) return error("mmap failed"); hdr = map; if (verify_hdr(hdr, size) < 0) goto unmap; active_nr = ntohl(hdr->hdr_entries); active_alloc = alloc_nr(active_nr); active_cache = calloc(active_alloc, sizeof(struct cache_entry *)); offset = sizeof(*hdr); for (i = 0; i < active_nr; i++) { struct cache_entry *ce = map + offset; offset = offset + ce_size(ce); active_cache[i] = ce; } return active_nr; unmap: munmap(map, size); errno = EINVAL; return error("verify header failed"); }
int process_hdr(const char *dev, int flags, unsigned char *pass, int passlen, struct tchdr_enc *ehdr, struct tcplay_info **pinfo) { struct tchdr_dec *dhdr; struct tcplay_info *info; struct tc_cipher_chain *cipher_chain = NULL; unsigned char *key; int i, j, found, error; *pinfo = NULL; if ((key = alloc_safe_mem(MAX_KEYSZ)) == NULL) { tc_log(1, "could not allocate safe key memory\n"); return ENOMEM; } /* Start search for correct algorithm combination */ found = 0; for (i = 0; !found && pbkdf_prf_algos[i].name != NULL; i++) { #ifdef DEBUG printf("\nTrying PRF algo %s (%d)\n", pbkdf_prf_algos[i].name, pbkdf_prf_algos[i].iteration_count); printf("Salt: "); print_hex(ehdr->salt, 0, sizeof(ehdr->salt)); #endif error = pbkdf2(&pbkdf_prf_algos[i], (char *)pass, passlen, ehdr->salt, sizeof(ehdr->salt), MAX_KEYSZ, key); if (error) { tc_log(1, "pbkdf failed for algorithm %s\n", pbkdf_prf_algos[i].name); free_safe_mem(key); return EINVAL; } #if 0 printf("Derived Key: "); print_hex(key, 0, MAX_KEYSZ); #endif for (j = 0; !found && tc_cipher_chains[j] != NULL; j++) { cipher_chain = tc_dup_cipher_chain(tc_cipher_chains[j]); #ifdef DEBUG printf("\nTrying cipher chain %d\n", j); #endif dhdr = decrypt_hdr(ehdr, cipher_chain, key); if (dhdr == NULL) { tc_log(1, "hdr decryption failed for cipher " "chain %d\n", j); free_safe_mem(key); return EINVAL; } if (verify_hdr(dhdr)) { #ifdef DEBUG printf("tc_str: %.4s, tc_ver: %d, tc_min_ver: %d, " "crc_keys: %d, sz_vol: %"PRIu64", " "off_mk_scope: %"PRIu64", sz_mk_scope: %"PRIu64", " "flags: %d, sec_sz: %d crc_dhdr: %d\n", dhdr->tc_str, dhdr->tc_ver, dhdr->tc_min_ver, dhdr->crc_keys, dhdr->sz_vol, dhdr->off_mk_scope, dhdr->sz_mk_scope, dhdr->flags, dhdr->sec_sz, dhdr->crc_dhdr); #endif found = 1; } else { free_safe_mem(dhdr); tc_free_cipher_chain(cipher_chain); } } } free_safe_mem(key); if (!found) return EINVAL; if ((info = new_info(dev, flags, cipher_chain, &pbkdf_prf_algos[i-1], dhdr, 0)) == NULL) { free_safe_mem(dhdr); return ENOMEM; } *pinfo = info; return 0; }