int LUKS_wipe_header_areas(struct luks_phdr *hdr, struct crypt_device *ctx) { int i, r; uint64_t offset, length; size_t wipe_block; /* Wipe complete header, keyslots and padding areas with zeroes. */ offset = 0; length = (uint64_t)hdr->payloadOffset * SECTOR_SIZE; wipe_block = 1024 * 1024; /* On detached header or bogus header, wipe at least the first 4k */ if (length == 0 || length > (LUKS_MAX_KEYSLOT_SIZE * LUKS_NUMKEYS)) { length = 4096; wipe_block = 4096; } log_dbg(ctx, "Wiping LUKS areas (0x%06" PRIx64 " - 0x%06" PRIx64") with zeroes.", offset, length + offset); r = crypt_wipe_device(ctx, crypt_metadata_device(ctx), CRYPT_WIPE_ZERO, offset, length, wipe_block, NULL, NULL); if (r < 0) return r; /* Wipe keyslots areas */ wipe_block = 1024 * 1024; for (i = 0; i < LUKS_NUMKEYS; i++) { r = LUKS_keyslot_area(hdr, i, &offset, &length); if (r < 0) return r; /* Ignore too big LUKS1 keyslots here */ if (length > LUKS_MAX_KEYSLOT_SIZE || offset > (LUKS_MAX_KEYSLOT_SIZE - length)) continue; if (length == 0 || offset < 4096) return -EINVAL; log_dbg(ctx, "Wiping keyslot %i area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.", i, offset, length + offset); r = crypt_wipe_device(ctx, crypt_metadata_device(ctx), CRYPT_WIPE_RANDOM, offset, length, wipe_block, NULL, NULL); if (r < 0) return r; } return r; }
static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struct json_object **keyslot_object) { char *base64_str, cipher[LUKS_CIPHERNAME_L+LUKS_CIPHERMODE_L]; size_t base64_len; struct json_object *keyslot_obj, *field, *jobj_kdf, *jobj_af, *jobj_area; uint64_t offset, area_size, offs_a, offs_b, length; keyslot_obj = json_object_new_object(); json_object_object_add(keyslot_obj, "type", json_object_new_string("luks2")); json_object_object_add(keyslot_obj, "key_size", json_object_new_int64(hdr_v1->keyBytes)); /* KDF */ jobj_kdf = json_object_new_object(); json_object_object_add(jobj_kdf, "type", json_object_new_string(CRYPT_KDF_PBKDF2)); json_object_object_add(jobj_kdf, "hash", json_object_new_string(hdr_v1->hashSpec)); json_object_object_add(jobj_kdf, "iterations", json_object_new_int64(hdr_v1->keyblock[keyslot].passwordIterations)); /* salt field */ base64_len = base64_encode_alloc(hdr_v1->keyblock[keyslot].passwordSalt, LUKS_SALTSIZE, &base64_str); if (!base64_str) { json_object_put(keyslot_obj); json_object_put(jobj_kdf); if (!base64_len) return -EINVAL; return -ENOMEM; } field = json_object_new_string_len(base64_str, base64_len); free(base64_str); json_object_object_add(jobj_kdf, "salt", field); json_object_object_add(keyslot_obj, "kdf", jobj_kdf); /* AF */ jobj_af = json_object_new_object(); json_object_object_add(jobj_af, "type", json_object_new_string("luks1")); json_object_object_add(jobj_af, "hash", json_object_new_string(hdr_v1->hashSpec)); /* stripes field ignored, fixed to LUKS_STRIPES (4000) */ json_object_object_add(jobj_af, "stripes", json_object_new_int(4000)); json_object_object_add(keyslot_obj, "af", jobj_af); /* Area */ jobj_area = json_object_new_object(); json_object_object_add(jobj_area, "type", json_object_new_string("raw")); /* encryption algorithm field */ if (*hdr_v1->cipherMode != '\0') { (void) snprintf(cipher, sizeof(cipher), "%s-%s", hdr_v1->cipherName, hdr_v1->cipherMode); json_object_object_add(jobj_area, "encryption", json_object_new_string(cipher)); } else json_object_object_add(jobj_area, "encryption", json_object_new_string(hdr_v1->cipherName)); /* area */ if (LUKS_keyslot_area(hdr_v1, 0, &offs_a, &length) || LUKS_keyslot_area(hdr_v1, 1, &offs_b, &length) || LUKS_keyslot_area(hdr_v1, keyslot, &offset, &length)) { json_object_put(keyslot_obj); json_object_put(jobj_area); return -EINVAL; } area_size = offs_b - offs_a; json_object_object_add(jobj_area, "key_size", json_object_new_int(hdr_v1->keyBytes)); json_object_object_add(jobj_area, "offset", json_object_new_uint64(offset)); json_object_object_add(jobj_area, "size", json_object_new_uint64(area_size)); json_object_object_add(keyslot_obj, "area", jobj_area); *keyslot_object = keyslot_obj; return 0; }