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 dc_backup_header(wchar_t *dev_name, dc_pass *password, void *out) { dc_header *header = NULL; xts_key *hdr_key = NULL; dev_hook *hook = NULL; int resl; s8 salt[PKCS5_SALT_SIZE]; do { if ( (hook = dc_find_hook(dev_name)) == NULL ) { resl = ST_NF_DEVICE; break; } wait_object_infinity(&hook->busy_lock); if (hook->flags & (F_SYNC | F_UNSUPRT | F_DISABLE | F_CDROM)) { resl = ST_ERROR; break; } if ( (hdr_key = mm_alloc(sizeof(xts_key), MEM_SECURE)) == NULL ) { resl = ST_NOMEM; break; } /* get device params */ if (hook->dsk_size == 0) { if ( (resl = dc_fill_disk_info(hook)) != ST_OK ) break; } if ( (resl = io_read_header(hook, &header, NULL, password)) != ST_OK ) { break; } /* generate new salt */ cp_rand_bytes(header->salt, PKCS5_SALT_SIZE); /* save original salt */ memcpy(salt, header->salt, PKCS5_SALT_SIZE); /* init new header key */ cp_set_header_key(hdr_key, header->salt, header->alg_1, password); /* encrypt header with new key */ xts_encrypt(pv(header), pv(header), sizeof(dc_header), 0, hdr_key); /* restore original salt */ memcpy(header->salt, salt, PKCS5_SALT_SIZE); /* copy header to output */ memcpy(out, header, sizeof(dc_header)); resl = ST_OK; } while (0); if (hook != NULL) { KeReleaseMutex(&hook->busy_lock, FALSE); dc_deref_hook(hook); } /* prevent leaks */ burn(salt, sizeof(salt)); /* free memory */ if (header != NULL) mm_free(header); if (hdr_key != NULL) mm_free(hdr_key); return resl; }
int dc_change_pass(wchar_t *dev_name, dc_pass *old_pass, dc_pass *new_pass) { dc_header *header = NULL; dev_hook *hook = NULL; int wp_init = 0; int resl; wipe_ctx wipe; 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) ) { resl = ST_NO_MOUNT; break; } if (hook->flags & (F_SYNC | F_FORMATTING | F_CDROM)) { resl = ST_ERROR; break; } /* read old volume header */ if ( (resl = io_read_header(hook, &header, NULL, old_pass)) != ST_OK ) { break; } /* init data wipe */ if ( (resl = dc_wipe_init( &wipe, hook, hook->head_len, WP_GUTMANN, hook->crypt.cipher_id)) == ST_OK ) { wp_init = 1; } else break; /* wipe volume header */ dc_wipe_process(&wipe, 0, hook->head_len); /* write new volume header */ resl = io_write_header(hook, header, NULL, new_pass); } while (0); if (wp_init != 0) { dc_wipe_free(&wipe); } if (hook != NULL) { KeReleaseMutex(&hook->busy_lock, FALSE); dc_deref_hook(hook); } if (header != NULL) mm_free(header); return resl; }