Skip to content

Commit 2d1e7e6

Browse files
committed
Allow parallel reencryption operations
1 parent a5b3288 commit 2d1e7e6

File tree

2 files changed

+85
-56
lines changed

2 files changed

+85
-56
lines changed

src/engine/strat_engine/cmd.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ const CLEVIS_EXEC_NAMES: &[&str] = &[
111111
CLEVIS_REGEN,
112112
JOSE,
113113
JQ,
114-
CRYPTSETUP,
115114
CURL,
116115
TPM2_CREATEPRIMARY,
117116
TPM2_UNSEAL,
@@ -132,6 +131,7 @@ static EXECUTABLES: LazyLock<HashMap<String, Option<PathBuf>>> = LazyLock::new(|
132131
THIN_METADATA_SIZE.to_string(),
133132
find_executable(THIN_METADATA_SIZE),
134133
),
134+
(CRYPTSETUP.to_string(), find_executable(CRYPTSETUP)),
135135
]
136136
.iter()
137137
.cloned()
@@ -575,3 +575,14 @@ pub fn thin_metadata_size(
575575
)))
576576
}
577577
}
578+
579+
pub fn run_reencrypt(path: &Path, _passphrase: &[u8]) -> StratisResult<()> {
580+
get_persistent_keyring()?;
581+
let mut cmd = Command::new(CRYPTSETUP);
582+
cmd.arg("reencrypt")
583+
.arg("--resume-only")
584+
.arg("--token-only")
585+
.arg(path);
586+
587+
execute_cmd(&mut cmd)
588+
}

src/engine/strat_engine/crypt/shared.rs

Lines changed: 73 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,33 @@ pub fn handle_setup_reencrypt(
11011101
luks2_path: &Path,
11021102
encryption_info: &EncryptionInfo,
11031103
) -> StratisResult<(u32, SizedKeyMemory, u32)> {
1104+
fn set_up_reencryption_token(
1105+
device: &mut CryptDevice,
1106+
new_keyslot: u32,
1107+
ts: u32,
1108+
mut token_contents: Value,
1109+
) -> StratisResult<()> {
1110+
if let Some(obj) = token_contents.as_object_mut() {
1111+
let tokens = match obj.remove(TOKEN_KEYSLOTS_KEY) {
1112+
Some(Value::Array(mut v)) => {
1113+
v.push(Value::String(new_keyslot.to_string()));
1114+
Value::Array(v)
1115+
}
1116+
Some(_) | None => {
1117+
return Err(StratisError::Msg(format!(
1118+
"Could not find appropriate formatted value for {TOKEN_KEYSLOTS_KEY}"
1119+
)));
1120+
}
1121+
};
1122+
obj.insert(TOKEN_KEYSLOTS_KEY.to_string(), tokens);
1123+
}
1124+
device
1125+
.token_handle()
1126+
.json_set(TokenInput::ReplaceToken(ts, &token_contents))?;
1127+
1128+
Ok(())
1129+
}
1130+
11041131
let mut device = acquire_crypt_device(luks2_path)?;
11051132

11061133
let mut keys = get_all_passphrases(&mut device, encryption_info)?;
@@ -1113,7 +1140,7 @@ pub fn handle_setup_reencrypt(
11131140
let (single_ts, single_key) = keys
11141141
.pop()
11151142
.ok_or_else(|| StratisError::Msg("No unlock methods found".to_string()))?;
1116-
let mut single_token_contents = device.token_handle().json_get(single_ts)?;
1143+
let single_token_contents = device.token_handle().json_get(single_ts)?;
11171144
let single_keyslot = get_keyslot_number(&mut device, single_ts)?.ok_or_else(|| {
11181145
StratisError::Msg(format!(
11191146
"Could not find keyslot associated with token slot {single_ts}"
@@ -1126,16 +1153,13 @@ pub fn handle_setup_reencrypt(
11261153
single_key.as_ref(),
11271154
CryptVolumeKey::NO_SEGMENT,
11281155
)?;
1129-
if let Some(obj) = single_token_contents.as_object_mut() {
1130-
obj.remove(TOKEN_KEYSLOTS_KEY);
1131-
obj.insert(
1132-
TOKEN_KEYSLOTS_KEY.to_string(),
1133-
Value::Array(vec![Value::String(single_new_keyslot.to_string())]),
1134-
);
1135-
}
1136-
device
1137-
.token_handle()
1138-
.json_set(TokenInput::ReplaceToken(single_ts, &single_token_contents))?;
1156+
1157+
set_up_reencryption_token(
1158+
&mut device,
1159+
single_new_keyslot,
1160+
single_ts,
1161+
single_token_contents,
1162+
)?;
11391163

11401164
let mut new_vk = SafeMemHandle::alloc(STRATIS_MEK_SIZE)?;
11411165
device.volume_key_handle().get(
@@ -1145,24 +1169,15 @@ pub fn handle_setup_reencrypt(
11451169
)?;
11461170

11471171
for (ts, key) in other_keys {
1148-
let mut token_contents = device.token_handle().json_get(ts)?;
1172+
let token_contents = device.token_handle().json_get(ts)?;
11491173

11501174
let new_keyslot = device.keyslot_handle().add_by_key(
11511175
None,
11521176
Some(Either::Left(new_vk.as_ref())),
11531177
key.as_ref(),
11541178
CryptVolumeKey::NO_SEGMENT | CryptVolumeKey::DIGEST_REUSE,
11551179
)?;
1156-
if let Some(obj) = token_contents.as_object_mut() {
1157-
obj.remove(TOKEN_KEYSLOTS_KEY);
1158-
obj.insert(
1159-
TOKEN_KEYSLOTS_KEY.to_string(),
1160-
Value::Array(vec![Value::String(new_keyslot.to_string())]),
1161-
);
1162-
}
1163-
device
1164-
.token_handle()
1165-
.json_set(TokenInput::ReplaceToken(ts, &token_contents))?;
1180+
set_up_reencryption_token(&mut device, new_keyslot, ts, token_contents)?;
11661181
}
11671182

11681183
Ok((single_keyslot, single_key, single_new_keyslot))
@@ -1179,41 +1194,44 @@ pub fn handle_do_reencrypt(
11791194
single_key: SizedKeyMemory,
11801195
single_new_keyslot: u32,
11811196
) -> StratisResult<()> {
1182-
let mut device = acquire_crypt_device(luks2_path)?;
1183-
1184-
let cipher = device.status_handle().get_cipher()?;
1185-
let cipher_mode = device.status_handle().get_cipher_mode()?;
1186-
let sector_size = convert_int!(get_sector_size(Some(&mut device)), i32, u32)?;
1187-
device.reencrypt_handle().reencrypt_init_by_passphrase(
1188-
Some(device_name),
1189-
single_key.as_ref(),
1190-
Some(single_keyslot),
1191-
Some(single_new_keyslot),
1192-
Some((&cipher, &cipher_mode)),
1193-
CryptParamsReencrypt {
1194-
mode: CryptReencryptModeInfo::Reencrypt,
1195-
direction: CryptReencryptDirectionInfo::Forward,
1196-
resilience: "checksum".to_string(),
1197-
hash: "sha256".to_string(),
1198-
data_shift: 0,
1199-
max_hotzone_size: 0,
1200-
device_size: 0,
1201-
luks2: Some(CryptParamsLuks2 {
1202-
data_alignment: 0,
1203-
data_device: None,
1204-
integrity: None,
1205-
integrity_params: None,
1206-
pbkdf: None,
1207-
label: None,
1208-
sector_size,
1209-
subsystem: None,
1210-
}),
1211-
flags: CryptReencrypt::empty(),
1212-
},
1213-
)?;
1197+
{
1198+
let mut device = acquire_crypt_device(luks2_path)?;
1199+
1200+
let cipher = device.status_handle().get_cipher()?;
1201+
let cipher_mode = device.status_handle().get_cipher_mode()?;
1202+
let sector_size = convert_int!(get_sector_size(Some(&mut device)), i32, u32)?;
1203+
device.reencrypt_handle().reencrypt_init_by_passphrase(
1204+
Some(device_name),
1205+
single_key.as_ref(),
1206+
Some(single_keyslot),
1207+
Some(single_new_keyslot),
1208+
Some((&cipher, &cipher_mode)),
1209+
CryptParamsReencrypt {
1210+
mode: CryptReencryptModeInfo::Reencrypt,
1211+
direction: CryptReencryptDirectionInfo::Forward,
1212+
resilience: "checksum".to_string(),
1213+
hash: "sha256".to_string(),
1214+
data_shift: 0,
1215+
max_hotzone_size: 0,
1216+
device_size: 0,
1217+
luks2: Some(CryptParamsLuks2 {
1218+
data_alignment: 0,
1219+
data_device: None,
1220+
integrity: None,
1221+
integrity_params: None,
1222+
pbkdf: None,
1223+
label: None,
1224+
sector_size,
1225+
subsystem: None,
1226+
}),
1227+
flags: CryptReencrypt::empty(),
1228+
},
1229+
)?;
1230+
}
12141231

12151232
info!("Starting reencryption operation on pool with UUID {pool_uuid}; may take a while");
1216-
device.reencrypt_handle().reencrypt2::<()>(None, None)?;
1233+
// The corresponding libcryptsetup call is device.reencrypt_handle().reencrypt2::<()>(None, None)?;
1234+
cmd::run_reencrypt(luks2_path, single_key.as_ref())?;
12171235

12181236
Ok(())
12191237
}

0 commit comments

Comments
 (0)