int LUKS_hdr_restore( const char *backup_file, struct luks_phdr *hdr, struct crypt_device *ctx) { struct device *device = crypt_metadata_device(ctx); int fd, r = 0, devfd = -1, diff_uuid = 0; ssize_t ret, buffer_size = 0; char *buffer = NULL, msg[200]; struct luks_phdr hdr_file; r = LUKS_read_phdr_backup(backup_file, &hdr_file, 0, ctx); if (r == -ENOENT) return r; if (!r) buffer_size = LUKS_device_sectors(&hdr_file) << SECTOR_SHIFT; if (r || buffer_size < LUKS_ALIGN_KEYSLOTS) { log_err(ctx, _("Backup file doesn't contain valid LUKS header.")); r = -EINVAL; goto out; } buffer = crypt_safe_alloc(buffer_size); if (!buffer) { r = -ENOMEM; goto out; } fd = open(backup_file, O_RDONLY); if (fd == -1) { log_err(ctx, _("Cannot open header backup file %s."), backup_file); r = -EINVAL; goto out; } ret = read_buffer(fd, buffer, buffer_size); close(fd); if (ret < buffer_size) { log_err(ctx, _("Cannot read header backup file %s."), backup_file); r = -EIO; goto out; } r = LUKS_read_phdr(hdr, 0, 0, ctx); if (r == 0) { log_dbg(ctx, "Device %s already contains LUKS header, checking UUID and offset.", device_path(device)); if(hdr->payloadOffset != hdr_file.payloadOffset || hdr->keyBytes != hdr_file.keyBytes) { log_err(ctx, _("Data offset or key size differs on device and backup, restore failed.")); r = -EINVAL; goto out; } if (memcmp(hdr->uuid, hdr_file.uuid, UUID_STRING_L)) diff_uuid = 1; } if (snprintf(msg, sizeof(msg), _("Device %s %s%s"), device_path(device), r ? _("does not contain LUKS header. Replacing header can destroy data on that device.") : _("already contains LUKS header. Replacing header will destroy existing keyslots."), diff_uuid ? _("\nWARNING: real device header has different UUID than backup!") : "") < 0) { r = -ENOMEM; goto out; } if (!crypt_confirm(ctx, msg)) { r = -EINVAL; goto out; } log_dbg(ctx, "Storing backup of header (%zu bytes) and keyslot area (%zu bytes) to device %s.", sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS, device_path(device)); devfd = device_open(ctx, device, O_RDWR); if (devfd < 0) { if (errno == EACCES) log_err(ctx, _("Cannot write to device %s, permission denied."), device_path(device)); else log_err(ctx, _("Cannot open device %s."), device_path(device)); r = -EINVAL; goto out; } if (write_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device), buffer, buffer_size, 0) < buffer_size) { r = -EIO; goto out; } /* Be sure to reload new data */ r = LUKS_read_phdr(hdr, 1, 0, ctx); out: device_sync(ctx, device); crypt_safe_free(buffer); return r; }
int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx) { struct device *device = crypt_metadata_device(ctx); struct luks_phdr hdr; int fd, devfd, r = 0; size_t hdr_size; size_t buffer_size; ssize_t ret; char *buffer = NULL; r = LUKS_read_phdr(&hdr, 1, 0, ctx); if (r) return r; hdr_size = LUKS_device_sectors(&hdr) << SECTOR_SHIFT; buffer_size = size_round_up(hdr_size, crypt_getpagesize()); buffer = crypt_safe_alloc(buffer_size); if (!buffer || hdr_size < LUKS_ALIGN_KEYSLOTS || hdr_size > buffer_size) { r = -ENOMEM; goto out; } log_dbg(ctx, "Storing backup of header (%zu bytes) and keyslot area (%zu bytes).", sizeof(hdr), hdr_size - LUKS_ALIGN_KEYSLOTS); log_dbg(ctx, "Output backup file size: %zu bytes.", buffer_size); devfd = device_open(ctx, device, O_RDONLY); if (devfd < 0) { log_err(ctx, _("Device %s is not a valid LUKS device."), device_path(device)); r = -EINVAL; goto out; } if (read_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device), buffer, hdr_size, 0) < (ssize_t)hdr_size) { r = -EIO; goto out; } /* Wipe unused area, so backup cannot contain old signatures */ if (hdr.keyblock[0].keyMaterialOffset * SECTOR_SIZE == LUKS_ALIGN_KEYSLOTS) memset(buffer + sizeof(hdr), 0, LUKS_ALIGN_KEYSLOTS - sizeof(hdr)); fd = open(backup_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR); if (fd == -1) { if (errno == EEXIST) log_err(ctx, _("Requested header backup file %s already exists."), backup_file); else log_err(ctx, _("Cannot create header backup file %s."), backup_file); r = -EINVAL; goto out; } ret = write_buffer(fd, buffer, buffer_size); close(fd); if (ret < (ssize_t)buffer_size) { log_err(ctx, _("Cannot write header backup file %s."), backup_file); r = -EIO; goto out; } r = 0; out: crypt_memzero(&hdr, sizeof(hdr)); crypt_safe_free(buffer); return r; }
print_properties(device *me) { const device_property *property; for (property = device_find_property(me, NULL); property != NULL; property = device_next_property(property)) { printf_filtered("%s/%s", device_path(me), property->name); if (property->original != NULL) { printf_filtered(" !"); printf_filtered("%s/%s", device_path(property->original->owner), property->original->name); } else { switch (property->type) { case array_property: if ((property->sizeof_array % sizeof(signed_cell)) == 0) { unsigned_cell *w = (unsigned_cell*)property->array; int cell_nr; for (cell_nr = 0; cell_nr < (property->sizeof_array / sizeof(unsigned_cell)); cell_nr++) { printf_filtered(" 0x%lx", (unsigned long)BE2H_cell(w[cell_nr])); } } else { unsigned8 *w = (unsigned8*)property->array; printf_filtered(" ["); while ((char*)w - (char*)property->array < property->sizeof_array) { printf_filtered(" 0x%2x", BE2H_1(*w)); w++; } } break; case boolean_property: { int b = device_find_boolean_property(me, property->name); printf_filtered(" %s", b ? "true" : "false"); } break; case ihandle_property: { if (property->array != NULL) { device_instance *instance = device_find_ihandle_property(me, property->name); printf_filtered(" *%s", device_instance_path(instance)); } else { /* not yet initialized, ask the device for the path */ ihandle_runtime_property_spec spec; device_find_ihandle_runtime_property(me, property->name, &spec); printf_filtered(" *%s", spec.full_path); } } break; case integer_property: { unsigned_word w = device_find_integer_property(me, property->name); printf_filtered(" 0x%lx", (unsigned long)w); } break; case range_array_property: print_ranges_property(me, property); break; case reg_array_property: print_reg_property(me, property); break; case string_property: { const char *s = device_find_string_property(me, property->name); print_string(s); } break; case string_array_property: print_string_array_property(me, property); break; } } printf_filtered("\n"); } }
static int VERITY_create_or_verify_hash(struct crypt_device *cd, int verify, int version, const char *hash_name, struct device *hash_device, struct device *data_device, size_t hash_block_size, size_t data_block_size, off_t data_blocks, off_t hash_position, char *root_hash, size_t digest_size, const char *salt, size_t salt_size) { char calculated_digest[digest_size]; FILE *data_file = NULL; FILE *hash_file = NULL, *hash_file_2; off_t hash_level_block[VERITY_MAX_LEVELS]; off_t hash_level_size[VERITY_MAX_LEVELS]; off_t data_file_blocks, s; size_t hash_per_block_bits; off_t data_device_size = 0, hash_device_size = 0; uint64_t dev_size; int levels, i, r; log_dbg("VERITY_create_or_verify_hash"); log_dbg("verify: %d", verify); log_dbg("hash_name: %s", hash_name); log_dbg("data_device: %s", device_path(data_device)); log_dbg("hash_block_size: %u", hash_block_size); log_dbg("data_block_size: %u", data_block_size); log_dbg("data_blocks: %lu", data_blocks); log_dbg("hash_device: %s", device_path(hash_device)); log_dbg("offset: %lu", hash_position); log_dbg("Hash %s %s, data device %s, data blocks %lu" ", hash_device %s, offset %lu.", verify ? "verification" : "creation", hash_name, device_path(data_device), data_blocks, device_path(hash_device), hash_position); if (data_blocks < 0 || hash_position < 0) { log_err(cd, "Invalid size parameters for verity device.\n"); return -EINVAL; } if (!data_blocks) { r = device_size(data_device, &dev_size); if (r < 0) return r; data_file_blocks = dev_size / data_block_size; } else data_file_blocks = data_blocks; if (mult_overflow(&data_device_size, data_blocks, data_block_size)) { log_err(cd, "Device offset overflow.\n"); return -EINVAL; } hash_per_block_bits = get_bits_down(hash_block_size / digest_size); if (!hash_per_block_bits) return -EINVAL; levels = 0; if (data_file_blocks) { while (hash_per_block_bits * levels < 64 && (data_file_blocks - 1) >> (hash_per_block_bits * levels)) levels++; } log_dbg("Using %d hash levels.", levels); if (levels > VERITY_MAX_LEVELS) { log_err(cd, "Too many tree levels for verity volume.\n"); return -EINVAL; } for (i = levels - 1; i >= 0; i--) { hash_level_block[i] = hash_position; // verity position of block data_file_blocks at level i s = (data_file_blocks + ((off_t)1 << ((i + 1) * hash_per_block_bits)) - 1) >> ((i + 1) * hash_per_block_bits); hash_level_size[i] = s; if ((hash_position + s) < hash_position || (hash_position + s) < 0) { log_err(cd, "Device offset overflow.\n"); return -EINVAL; } hash_position += s; } if (mult_overflow(&hash_device_size, hash_position, hash_block_size)) { log_err(cd, "Device offset overflow.\n"); return -EINVAL; } //log_dbg("Data device size required: %" PRIu64 " bytes.", // data_device_size); log_dbg("Data device size required: %lu bytes.", data_device_size); data_file = fopen(device_path(data_device), "r"); if (!data_file) { log_err(cd, "Cannot open device %s.\n", device_path(data_device) ); r = -EIO; goto out; } //log_dbg("Hash device size required: %" PRIu64 " bytes.", // hash_device_size); log_dbg("Hash device size required: %lu bytes.", hash_device_size); hash_file = fopen(device_path(hash_device), verify ? "r" : "r+"); if (!hash_file) { log_err(cd, "Cannot open device %s.\n", device_path(hash_device)); r = -EIO; goto out; } memset(calculated_digest, 0, digest_size); for (i = 0; i < levels; i++) { if (!i) { r = create_or_verify(cd, data_file, hash_file, 0, data_block_size, hash_level_block[i], hash_block_size, data_file_blocks, version, hash_name, verify, calculated_digest, digest_size, salt, salt_size); if (r) goto out; } else { hash_file_2 = fopen(device_path(hash_device), "r"); if (!hash_file_2) { log_err(cd, "Cannot open device %s.\n", device_path(hash_device)); r = -EIO; goto out; } r = create_or_verify(cd, hash_file_2, hash_file, hash_level_block[i - 1], hash_block_size, hash_level_block[i], hash_block_size, hash_level_size[i - 1], version, hash_name, verify, calculated_digest, digest_size, salt, salt_size); fclose(hash_file_2); if (r) goto out; } } if (levels) r = create_or_verify(cd, hash_file, NULL, hash_level_block[levels - 1], hash_block_size, 0, hash_block_size, 1, version, hash_name, verify, calculated_digest, digest_size, salt, salt_size); else r = create_or_verify(cd, data_file, NULL, 0, data_block_size, 0, hash_block_size, data_file_blocks, version, hash_name, verify, calculated_digest, digest_size, salt, salt_size); out: if (verify) { if (r) log_err(cd, "Verification of data area failed.\n"); else { log_dbg("Verification of data area succeeded."); r = memcmp(root_hash, calculated_digest, digest_size) ? -EPERM : 0; if (r) log_err(cd, "Verification of root hash failed.\n"); else log_dbg("Verification of root hash succeeded."); } } else { if (r == -EIO) log_err(cd, "Input/output error while creating hash area.\n"); else if (r) log_err(cd, "Creation of hash area failed.\n"); else { fsync(fileno(hash_file)); memcpy(root_hash, calculated_digest, digest_size); } } if (data_file) fclose(data_file); if (hash_file) fclose(hash_file); return r; }
/* Read verity superblock from disk */ int VERITY_read_sb(struct crypt_device *cd, uint64_t sb_offset, char **uuid_string, struct crypt_params_verity *params) { struct device *device = crypt_metadata_device(cd); int bsize = device_block_size(device); struct verity_sb sb = {}; ssize_t hdr_size = sizeof(struct verity_sb); int devfd = 0, sb_version; log_dbg("Reading VERITY header of size %zu on device %s, offset %" PRIu64 ".", sizeof(struct verity_sb), device_path(device), sb_offset); if (params->flags & CRYPT_VERITY_NO_HEADER) { log_err(cd, _("Verity device %s doesn't use on-disk header.\n"), device_path(device)); return -EINVAL; } if (sb_offset % 512) { log_err(cd, _("Unsupported VERITY hash offset.\n")); return -EINVAL; } devfd = device_open(device, O_RDONLY); if(devfd == -1) { log_err(cd, _("Cannot open device %s.\n"), device_path(device)); return -EINVAL; } if(lseek(devfd, sb_offset, SEEK_SET) < 0 || read_blockwise(devfd, bsize, &sb, hdr_size) < hdr_size) { close(devfd); return -EIO; } close(devfd); if (memcmp(sb.signature, VERITY_SIGNATURE, sizeof(sb.signature))) { log_err(cd, _("Device %s is not a valid VERITY device.\n"), device_path(device)); return -EINVAL; } sb_version = le32_to_cpu(sb.version); if (sb_version != 1) { log_err(cd, _("Unsupported VERITY version %d.\n"), sb_version); return -EINVAL; } params->hash_type = le32_to_cpu(sb.hash_type); if (params->hash_type > VERITY_MAX_HASH_TYPE) { log_err(cd, _("Unsupported VERITY hash type %d.\n"), params->hash_type); return -EINVAL; } params->data_block_size = le32_to_cpu(sb.data_block_size); params->hash_block_size = le32_to_cpu(sb.hash_block_size); if (VERITY_BLOCK_SIZE_OK(params->data_block_size) || VERITY_BLOCK_SIZE_OK(params->hash_block_size)) { log_err(cd, _("Unsupported VERITY block size.\n")); return -EINVAL; } params->data_size = le64_to_cpu(sb.data_blocks); params->hash_name = strndup((const char*)sb.algorithm, sizeof(sb.algorithm)); if (!params->hash_name) return -ENOMEM; if (crypt_hash_size(params->hash_name) <= 0) { log_err(cd, _("Hash algorithm %s not supported.\n"), params->hash_name); free(CONST_CAST(char*)params->hash_name); return -EINVAL; } params->salt_size = le16_to_cpu(sb.salt_size); if (params->salt_size > sizeof(sb.salt)) { log_err(cd, _("VERITY header corrupted.\n")); free(CONST_CAST(char*)params->hash_name); return -EINVAL; } params->salt = malloc(params->salt_size); if (!params->salt) { free(CONST_CAST(char*)params->hash_name); return -ENOMEM; } memcpy(CONST_CAST(char*)params->salt, sb.salt, params->salt_size); if ((*uuid_string = malloc(40))) uuid_unparse(sb.uuid, *uuid_string); params->hash_area_offset = sb_offset; return 0; }
// Find and connect Wiimotes. // Does not replace already found Wiimotes even if they are disconnected. // wm is an array of max_wiimotes Wiimotes // Returns the total number of found and connected Wiimotes. void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimote* & found_board) { if (!s_loaded_ok) return; ProcessWiimotes(true, [](HANDLE hRadio, const BLUETOOTH_RADIO_INFO& rinfo, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) { ForgetWiimote(btdi); AttachWiimote(hRadio, rinfo, btdi); }); // Get the device id GUID device_id; pHidD_GetHidGuid(&device_id); // Get all hid devices connected HDEVINFO const device_info = SetupDiGetClassDevs(&device_id, nullptr, nullptr, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); SP_DEVICE_INTERFACE_DATA device_data; device_data.cbSize = sizeof(device_data); PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = nullptr; for (int index = 0; SetupDiEnumDeviceInterfaces(device_info, nullptr, &device_id, index, &device_data); ++index) { // Get the size of the data block required DWORD len; SetupDiGetDeviceInterfaceDetail(device_info, &device_data, nullptr, 0, &len, nullptr); detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(len); detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // Query the data for this device if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, nullptr, nullptr)) { std::basic_string<TCHAR> device_path(detail_data->DevicePath); Wiimote* wm = new WiimoteWindows(device_path); bool real_wiimote = false, is_bb = false; CheckDeviceType(device_path, real_wiimote, is_bb); if (is_bb) { found_board = wm; } else if (real_wiimote) { found_wiimotes.push_back(wm); } else { delete wm; } } free(detail_data); } SetupDiDestroyDeviceInfoList(device_info); // Don't mind me, just a random sleep to fix stuff on Windows //if (!wiimotes.empty()) // SLEEP(2000); }