static int dc_probe_decrypt(dev_hook *hook, dc_header **header, xts_key **res_key, dc_pass *password) { xts_key *hdr_key; dsk_pass *d_pass; int resl, succs; hdr_key = NULL; succs = 0; *header = NULL; do { /* read raw volume header */ if ( (resl = io_read_header(hook, header, NULL, NULL)) != ST_OK ) { break; } if ( (hdr_key = mm_secure_alloc(sizeof(xts_key))) == NULL ) { resl = ST_NOMEM; break; } /* derive header key and decrypt header */ do { if (password != NULL) { /* probe mount with entered password */ if (succs = cp_decrypt_header(hdr_key, *header, password)) { break; } } KeEnterCriticalRegion(); ExAcquireResourceSharedLite(&p_resource, TRUE); /* probe mount with cached passwords */ for (d_pass = f_pass; d_pass; d_pass = d_pass->next) { if (succs = cp_decrypt_header(hdr_key, *header, &d_pass->pass)) { break; } } ExReleaseResourceLite(&p_resource); KeLeaveCriticalRegion(); } while (0); if (succs != 0) { *res_key = hdr_key; hdr_key = NULL; resl = ST_OK; } else { resl = ST_PASS_ERR; } } while (0); if (resl != ST_OK && *header != NULL) { mm_secure_free(*header); *header = NULL; } if (hdr_key != NULL) { mm_secure_free(hdr_key); } return resl; }
int io_read_header(dev_hook *hook, dc_header **header, xts_key **out_key, dc_pass *password) { xts_key *hdr_key = NULL; int hdr_len = max(sizeof(dc_header), hook->bps); int resl; /* allocate memory for header */ if ( (*header = mm_alloc(hdr_len, MEM_SECURE | MEM_SUCCESS)) == NULL ) return ST_NOMEM; do { /* read volume header */ if ( (resl = io_hook_rw(hook, *header, hdr_len, 0, 1)) != ST_OK ) break; /* decrypt volume header */ if (password != NULL) { /* allocate memory for header key */ if ( (hdr_key = mm_alloc(sizeof(xts_key), MEM_SECURE)) == NULL ) { resl = ST_NOMEM; break; } /* try to decrypt header */ if (cp_decrypt_header(hdr_key, *header, password) == 0) { resl = ST_PASS_ERR; break; } /* save decrypted header and key */ if (out_key != NULL) { *out_key = hdr_key; hdr_key = NULL; } } } while (0); if (resl != ST_OK) { mm_free(*header); *header = NULL; } if (hdr_key != NULL) mm_free(hdr_key); return resl; }
int dc_restore_header(wchar_t *dev_name, dc_pass *password, void *in) { dc_header *header = NULL; xts_key *hdr_key = NULL; dev_hook *hook = NULL; int resl; do { if ( (hook = dc_find_hook(dev_name)) == NULL ) { resl = ST_NF_DEVICE; break; } wait_object_infinity(&hook->busy_lock); if (hook->flags & (F_ENABLED | F_CDROM)) { resl = ST_ERROR; break; } /* get device params */ if (hook->dsk_size == 0) { if ( (resl = dc_fill_disk_info(hook)) != ST_OK ) break; } if ( (header = mm_alloc(sizeof(dc_header), MEM_SECURE)) == NULL ) { resl = ST_NOMEM; break; } /* copy header from input */ memcpy(header, in, sizeof(dc_header)); if ( (hdr_key = mm_alloc(sizeof(xts_key), MEM_SECURE)) == NULL ) { resl = ST_NOMEM; break; } /* decrypt header */ if (cp_decrypt_header(hdr_key, header, password) == 0) { resl = ST_PASS_ERR; break; } /* write new volume header */ resl = io_write_header(hook, header, NULL, password); } while (0); if (hook != NULL) { KeReleaseMutex(&hook->busy_lock, FALSE); dc_deref_hook(hook); } if (hdr_key != NULL) mm_free(hdr_key); if (header != NULL) mm_free(header); return resl; }