int device_block_size(struct device *device) { struct stat st; int fd, bsize = 0, r = -EINVAL; if (!device) return 0; fd = open(device->path, O_RDONLY); if(fd < 0) return -EINVAL; if (fstat(fd, &st) < 0) goto out; if (S_ISREG(st.st_mode) || device->file_path) { r = (int)crypt_getpagesize(); goto out; } if (ioctl(fd, BLKSSZGET, &bsize) >= 0) r = bsize; out: close(fd); return r; }
/* Create verity hash */ int VERITY_create(struct crypt_device *cd, struct crypt_params_verity *verity_hdr, char *root_hash, size_t root_hash_size) { unsigned pgsize = crypt_getpagesize(); if (verity_hdr->salt_size > 256) return -EINVAL; if (verity_hdr->data_block_size > pgsize) log_err(cd, "WARNING: Kernel cannot activate device if data " "block size exceeds page size (%u).\n", pgsize); off_t sz = verity_hdr->data_size; return VERITY_create_or_verify_hash(cd, 0, verity_hdr->hash_type, verity_hdr->hash_name, crypt_metadata_device(cd), crypt_data_device(cd), verity_hdr->hash_block_size, verity_hdr->data_block_size, verity_hdr->data_size, VERITY_hash_offset_block(verity_hdr), root_hash, root_hash_size, verity_hdr->salt, verity_hdr->salt_size); }
static int cipher_perf(struct cipher_perf *cp, double *encryption_mbs, double *decryption_mbs) { long ms_enc, ms_dec, ms; int repeat_enc, repeat_dec; void *buf = NULL; if (posix_memalign(&buf, crypt_getpagesize(), cp->buffer_size)) return -ENOMEM; ms_enc = 0; repeat_enc = 1; while (ms_enc < 1000) { ms = cipher_measure(cp, buf, cp->buffer_size, 1); if (ms < 0) { free(buf); return (int)ms; } ms_enc += ms; repeat_enc++; } ms_dec = 0; repeat_dec = 1; while (ms_dec < 1000) { ms = cipher_measure(cp, buf, cp->buffer_size, 0); if (ms < 0) { free(buf); return (int)ms; } ms_dec += ms; repeat_dec++; } free(buf); *encryption_mbs = speed_mbs(cp->buffer_size * repeat_enc, ms_enc); *decryption_mbs = speed_mbs(cp->buffer_size * repeat_dec, ms_dec); return 0; }
int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx) { struct device *device = crypt_metadata_device(ctx); struct luks_phdr hdr; int r = 0, devfd = -1; ssize_t hdr_size; ssize_t buffer_size; char *buffer = NULL; r = LUKS_read_phdr(&hdr, 1, 0, ctx); if (r) return r; hdr_size = LUKS_device_sectors(hdr.keyBytes) << 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("Storing backup of header (%zu bytes) and keyslot area (%zu bytes).", sizeof(hdr), hdr_size - LUKS_ALIGN_KEYSLOTS); log_dbg("Output backup file size: %zu bytes.", buffer_size); devfd = device_open(device, O_RDONLY); if(devfd == -1) { log_err(ctx, _("Device %s is not a valid LUKS device.\n"), device_path(device)); r = -EINVAL; goto out; } if (read_blockwise(devfd, device_block_size(device), buffer, hdr_size) < hdr_size) { r = -EIO; goto out; } close(devfd); /* 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)); devfd = open(backup_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR); if (devfd == -1) { if (errno == EEXIST) log_err(ctx, _("Requested header backup file %s already exists.\n"), backup_file); else log_err(ctx, _("Cannot create header backup file %s.\n"), backup_file); r = -EINVAL; goto out; } if (write(devfd, buffer, buffer_size) < buffer_size) { log_err(ctx, _("Cannot write header backup file %s.\n"), backup_file); r = -EIO; goto out; } close(devfd); r = 0; out: if (devfd != -1) close(devfd); crypt_memzero(&hdr, sizeof(hdr)); crypt_safe_free(buffer); return r; }
static int TCRYPT_init_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, struct crypt_params_tcrypt *params) { unsigned char pwd[TCRYPT_KEY_POOL_LEN] = {}; size_t passphrase_size; char *key; unsigned int i, skipped = 0; int r = -EPERM; if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN)) return -ENOMEM; if (params->keyfiles_count) passphrase_size = TCRYPT_KEY_POOL_LEN; else passphrase_size = params->passphrase_size; if (params->passphrase_size > TCRYPT_KEY_POOL_LEN) { log_err(cd, _("Maximum TCRYPT passphrase length (%d) exceeded.\n"), TCRYPT_KEY_POOL_LEN); goto out; } /* Calculate pool content from keyfiles */ for (i = 0; i < params->keyfiles_count; i++) { r = TCRYPT_pool_keyfile(cd, pwd, params->keyfiles[i]); if (r < 0) goto out; } /* If provided password, combine it with pool */ for (i = 0; i < params->passphrase_size; i++) pwd[i] += params->passphrase[i]; for (i = 0; tcrypt_kdf[i].name; i++) { if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_kdf[i].legacy) continue; if (!(params->flags & CRYPT_TCRYPT_VERA_MODES) && tcrypt_kdf[i].veracrypt) continue; /* Derive header key */ log_dbg("TCRYPT: trying KDF: %s-%s-%d.", tcrypt_kdf[i].name, tcrypt_kdf[i].hash, tcrypt_kdf[i].iterations); r = crypt_pbkdf(tcrypt_kdf[i].name, tcrypt_kdf[i].hash, (char*)pwd, passphrase_size, hdr->salt, TCRYPT_HDR_SALT_LEN, key, TCRYPT_HDR_KEY_LEN, tcrypt_kdf[i].iterations); if (r < 0 && crypt_hash_size(tcrypt_kdf[i].hash) < 0) { log_verbose(cd, _("PBKDF2 hash algorithm %s not available, skipping.\n"), tcrypt_kdf[i].hash); continue; } if (r < 0) break; /* Decrypt header */ r = TCRYPT_decrypt_hdr(cd, hdr, key, params->flags); if (r == -ENOENT) { skipped++; r = -EPERM; } if (r != -EPERM) break; } if ((r < 0 && r != -EPERM && skipped && skipped == i) || r == -ENOTSUP) { log_err(cd, _("Required kernel crypto interface not available.\n")); #ifdef ENABLE_AF_ALG log_err(cd, _("Ensure you have algif_skcipher kernel module loaded.\n")); #endif } if (r < 0) goto out; r = TCRYPT_hdr_from_disk(hdr, params, i, r); if (!r) { log_dbg("TCRYPT: Magic: %s, Header version: %d, req. %d, sector %d" ", mk_offset %" PRIu64 ", hidden_size %" PRIu64 ", volume size %" PRIu64, tcrypt_kdf[i].veracrypt ? VCRYPT_HDR_MAGIC : TCRYPT_HDR_MAGIC, (int)hdr->d.version, (int)hdr->d.version_tc, (int)hdr->d.sector_size, hdr->d.mk_offset, hdr->d.hidden_volume_size, hdr->d.volume_size); log_dbg("TCRYPT: Header cipher %s-%s, key size %zu", params->cipher, params->mode, params->key_size); } out: crypt_memzero(pwd, TCRYPT_KEY_POOL_LEN); if (key) crypt_memzero(key, TCRYPT_HDR_KEY_LEN); free(key); return r; }