密钥恢复优化
This commit is contained in:
+61
@@ -0,0 +1,61 @@
|
||||
package com.cisd.tms.integration.crypto.pcie.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MasterKeyRecoveryRequest {
|
||||
|
||||
private byte[] oldPin;
|
||||
private byte[] newPin;
|
||||
private byte[] lmkComponent;
|
||||
private byte[] authIkComponent;
|
||||
private byte[] deviceIkComponent;
|
||||
private List<RecoverUserKeyRequest> userKeyRequests;
|
||||
|
||||
public byte[] getOldPin() {
|
||||
return oldPin;
|
||||
}
|
||||
|
||||
public void setOldPin(byte[] oldPin) {
|
||||
this.oldPin = oldPin;
|
||||
}
|
||||
|
||||
public byte[] getNewPin() {
|
||||
return newPin;
|
||||
}
|
||||
|
||||
public void setNewPin(byte[] newPin) {
|
||||
this.newPin = newPin;
|
||||
}
|
||||
|
||||
public byte[] getLmkComponent() {
|
||||
return lmkComponent;
|
||||
}
|
||||
|
||||
public void setLmkComponent(byte[] lmkComponent) {
|
||||
this.lmkComponent = lmkComponent;
|
||||
}
|
||||
|
||||
public byte[] getAuthIkComponent() {
|
||||
return authIkComponent;
|
||||
}
|
||||
|
||||
public void setAuthIkComponent(byte[] authIkComponent) {
|
||||
this.authIkComponent = authIkComponent;
|
||||
}
|
||||
|
||||
public byte[] getDeviceIkComponent() {
|
||||
return deviceIkComponent;
|
||||
}
|
||||
|
||||
public void setDeviceIkComponent(byte[] deviceIkComponent) {
|
||||
this.deviceIkComponent = deviceIkComponent;
|
||||
}
|
||||
|
||||
public List<RecoverUserKeyRequest> getUserKeyRequests() {
|
||||
return userKeyRequests;
|
||||
}
|
||||
|
||||
public void setUserKeyRequests(List<RecoverUserKeyRequest> userKeyRequests) {
|
||||
this.userKeyRequests = userKeyRequests;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.cisd.tms.integration.crypto.pcie.model;
|
||||
|
||||
public class MasterKeyRecoveryResult {
|
||||
|
||||
private byte[] lmkSeedMac;
|
||||
private DeviceStatusResult deviceStatus;
|
||||
|
||||
public byte[] getLmkSeedMac() {
|
||||
return lmkSeedMac;
|
||||
}
|
||||
|
||||
public void setLmkSeedMac(byte[] lmkSeedMac) {
|
||||
this.lmkSeedMac = lmkSeedMac;
|
||||
}
|
||||
|
||||
public DeviceStatusResult getDeviceStatus() {
|
||||
return deviceStatus;
|
||||
}
|
||||
|
||||
public void setDeviceStatus(DeviceStatusResult deviceStatus) {
|
||||
this.deviceStatus = deviceStatus;
|
||||
}
|
||||
}
|
||||
+101
-10
@@ -12,6 +12,7 @@ import com.sun.jna.ptr.PointerByReference;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class JnaPcieCryptoService implements PcieCryptoService {
|
||||
@@ -177,16 +178,7 @@ public class JnaPcieCryptoService implements PcieCryptoService {
|
||||
@Override
|
||||
public DeviceStatusResult getDeviceStatus() {
|
||||
return sessionTemplate.withSession("SDFE_DeviceStatusGet", (lib, deviceHandle, sessionHandle) -> {
|
||||
SdfeDeviceStatus status = new SdfeDeviceStatus();
|
||||
sessionTemplate.ensureSuccess("SDFE_DeviceStatusGet", lib.SDFE_DeviceStatusGet(sessionHandle, status));
|
||||
status.read();
|
||||
int size = status.size();
|
||||
|
||||
DeviceStatusResult result = new DeviceStatusResult();
|
||||
result.setLength(size);
|
||||
result.setStatusData(status.getPointer().getByteArray(0, size));
|
||||
PcieDeviceStatusFormatter.enrich(result, status);
|
||||
return result;
|
||||
return readDeviceStatus(lib, sessionHandle);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1928,6 +1920,57 @@ public class JnaPcieCryptoService implements PcieCryptoService {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public MasterKeyRecoveryResult recoverMasterKeyMaterial(MasterKeyRecoveryRequest request) {
|
||||
MasterKeyRecoveryRequest req = requireRequest("request", request);
|
||||
byte[] oldPin = requireNonEmptyBytes("oldPin", req.getOldPin());
|
||||
byte[] newPin = requireNonEmptyBytes("newPin", req.getNewPin());
|
||||
SdfeLmkComponent lmkComponent = toSdfeLmkComponent("lmkComponent", req.getLmkComponent());
|
||||
SdfeIkComponent authIkComponent = toSdfeIkComponent("authIkComponent", req.getAuthIkComponent());
|
||||
SdfeIkComponent deviceIkComponent = toSdfeIkComponent("deviceIkComponent", req.getDeviceIkComponent());
|
||||
List<RecoverUserKeyRequest> userKeyRequests = requireUserKeyRequests(req.getUserKeyRequests());
|
||||
|
||||
try {
|
||||
return sessionTemplate.withSession("SDFE_RecoverMasterKeyMaterial", (lib, deviceHandle, sessionHandle) -> {
|
||||
sessionTemplate.ensureSuccess(
|
||||
"SDFE_InitIdentify",
|
||||
lib.SDFE_InitIdentify(sessionHandle, oldPin, oldPin.length, newPin, newPin.length)
|
||||
);
|
||||
sessionTemplate.ensureSuccess("SDFE_RecoverLMK_EX", lib.SDFE_RecoverLMK_EX(sessionHandle, lmkComponent));
|
||||
sessionTemplate.ensureSuccess("SDFE_LoadLMK", lib.SDFE_LoadLMK(sessionHandle));
|
||||
sessionTemplate.ensureSuccess(
|
||||
"SDFE_RecoverIK_EX",
|
||||
lib.SDFE_RecoverIK_EX(sessionHandle, IK_KEY_TYPE_AUTH, authIkComponent)
|
||||
);
|
||||
sessionTemplate.ensureSuccess(
|
||||
"SDFE_RecoverIK_EX",
|
||||
lib.SDFE_RecoverIK_EX(sessionHandle, IK_KEY_TYPE_DEVICE, deviceIkComponent)
|
||||
);
|
||||
DeviceStatusResult deviceStatus = readDeviceStatus(lib, sessionHandle);
|
||||
for (RecoverUserKeyRequest userKeyRequest : userKeyRequests) {
|
||||
recoverUserKeyInCurrentSession(lib, sessionHandle, userKeyRequest);
|
||||
}
|
||||
sessionTemplate.ensureSuccess("SDFE_CheckLMK", lib.SDFE_CheckLMK(sessionHandle));
|
||||
byte[] mac = new byte[LMK_SEED_MAC_LENGTH];
|
||||
sessionTemplate.ensureSuccess("SDFE_ExportLMKSeedMAC", lib.SDFE_ExportLMKSeedMAC(sessionHandle, mac));
|
||||
|
||||
MasterKeyRecoveryResult result = new MasterKeyRecoveryResult();
|
||||
result.setDeviceStatus(deviceStatus);
|
||||
result.setLmkSeedMac(Arrays.copyOf(mac, mac.length));
|
||||
return result;
|
||||
});
|
||||
} finally {
|
||||
wipe(oldPin);
|
||||
wipe(newPin);
|
||||
wipe(req.getLmkComponent());
|
||||
wipe(req.getAuthIkComponent());
|
||||
wipe(req.getDeviceIkComponent());
|
||||
for (RecoverUserKeyRequest userKeyRequest : userKeyRequests) {
|
||||
wipe(userKeyRequest.getEncryptedKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateIk(int keyType) {
|
||||
int safeKeyType = requireNonNegative("keyType", keyType);
|
||||
@@ -2057,6 +2100,54 @@ public class JnaPcieCryptoService implements PcieCryptoService {
|
||||
});
|
||||
}
|
||||
|
||||
private DeviceStatusResult readDeviceStatus(PcieNativeLibrary lib, Pointer sessionHandle) {
|
||||
SdfeDeviceStatus status = new SdfeDeviceStatus();
|
||||
sessionTemplate.ensureSuccess("SDFE_DeviceStatusGet", lib.SDFE_DeviceStatusGet(sessionHandle, status));
|
||||
status.read();
|
||||
int size = status.size();
|
||||
|
||||
DeviceStatusResult result = new DeviceStatusResult();
|
||||
result.setLength(size);
|
||||
result.setStatusData(status.getPointer().getByteArray(0, size));
|
||||
PcieDeviceStatusFormatter.enrich(result, status);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<RecoverUserKeyRequest> requireUserKeyRequests(List<RecoverUserKeyRequest> requests) {
|
||||
if (requests == null || requests.isEmpty()) {
|
||||
throw new IllegalArgumentException("userKeyRequests must not be empty");
|
||||
}
|
||||
for (RecoverUserKeyRequest request : requests) {
|
||||
RecoverUserKeyRequest req = requireRequest("userKeyRequest", request);
|
||||
requireNonNegative("keyIndex", req.getKeyIndex());
|
||||
requireUserKeyType(req.getKeyType());
|
||||
requireNonEmptyBytes("encryptedKey", req.getEncryptedKey());
|
||||
int storeFlag = req.getStoreFlag();
|
||||
if (storeFlag != 0 && storeFlag != 1) {
|
||||
throw new IllegalArgumentException("storeFlag必须为0或1");
|
||||
}
|
||||
}
|
||||
return List.copyOf(requests);
|
||||
}
|
||||
|
||||
private void recoverUserKeyInCurrentSession(
|
||||
PcieNativeLibrary lib,
|
||||
Pointer sessionHandle,
|
||||
RecoverUserKeyRequest request
|
||||
) {
|
||||
sessionTemplate.ensureSuccess(
|
||||
"SDFE_RecoverUserKey",
|
||||
lib.SDFE_RecoverUserKey(
|
||||
sessionHandle,
|
||||
request.getKeyIndex(),
|
||||
request.getKeyType(),
|
||||
request.getEncryptedKey(),
|
||||
request.getEncryptedKey().length,
|
||||
(byte) request.getStoreFlag()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface KeyHandleCallback<T> {
|
||||
T apply(Pointer keyHandle);
|
||||
|
||||
@@ -63,6 +63,8 @@ import com.cisd.tms.integration.crypto.pcie.model.IkVerifyRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.KekComponentRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.KeyStatusResult;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.MacCalcRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.MasterKeyRecoveryRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.MasterKeyRecoveryResult;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.PrivateKeyAccessRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.RecoverKekRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.RecoverUserKeyRequest;
|
||||
@@ -904,6 +906,28 @@ public class MockPcieCryptoService implements PcieCryptoService {
|
||||
requireNonEmptyBytes("lmkComponent", lmkComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MasterKeyRecoveryResult recoverMasterKeyMaterial(MasterKeyRecoveryRequest request) {
|
||||
MasterKeyRecoveryRequest req = requireRequest("request", request);
|
||||
initIdentify(req.getOldPin(), req.getNewPin());
|
||||
recoverLmkEx(req.getLmkComponent());
|
||||
loadLmk();
|
||||
recoverIkComponent(2, req.getAuthIkComponent());
|
||||
recoverIkComponent(1, req.getDeviceIkComponent());
|
||||
if (req.getUserKeyRequests() == null || req.getUserKeyRequests().isEmpty()) {
|
||||
throw new IllegalArgumentException("userKeyRequests must not be empty");
|
||||
}
|
||||
req.getUserKeyRequests().forEach(this::recoverUserKey);
|
||||
if (!checkLmk()) {
|
||||
throw new IllegalStateException("主密钥恢复后校验失败");
|
||||
}
|
||||
|
||||
MasterKeyRecoveryResult result = new MasterKeyRecoveryResult();
|
||||
result.setDeviceStatus(getDeviceStatus());
|
||||
result.setLmkSeedMac(exportLmkSeedMac());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateIk(int keyType) {
|
||||
requireNonNegative("keyType", keyType);
|
||||
|
||||
@@ -53,6 +53,8 @@ import com.cisd.tms.integration.crypto.pcie.model.IkVerifyRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.KekComponentRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.KeyStatusResult;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.MacCalcRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.MasterKeyRecoveryRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.MasterKeyRecoveryResult;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.PrivateKeyAccessRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.RecoverKekRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.RecoverUserKeyRequest;
|
||||
@@ -564,6 +566,11 @@ public interface PcieCryptoService {
|
||||
*/
|
||||
void recoverLmkEx(byte[] lmkComponent);
|
||||
|
||||
/**
|
||||
* 在单个设备 session 中恢复 LMK、IK 和用户密钥,并返回恢复后的 LMK seed MAC。
|
||||
*/
|
||||
MasterKeyRecoveryResult recoverMasterKeyMaterial(MasterKeyRecoveryRequest request);
|
||||
|
||||
|
||||
//----------------------------------------IK 生命周期类接口。------------------------------------------
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@ public interface LmkService {
|
||||
|
||||
String getComponent(int uid);
|
||||
|
||||
void recoverKeyPackets(List<MasterKeyBackupPacket> packets);
|
||||
MasterKeyStateResult recoverKeyPackets(List<MasterKeyBackupPacket> packets);
|
||||
|
||||
void recoverLmkEx(String lmkMacHex, List<String> components);
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ public class LmkServiceImpl implements LmkService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recoverKeyPackets(List<MasterKeyBackupPacket> packets) {
|
||||
public MasterKeyStateResult recoverKeyPackets(List<MasterKeyBackupPacket> packets) {
|
||||
// 进入恢复流程后,旧的备份轮次缓存不再可信,避免和恢复后的新密钥体系混用。
|
||||
clearCachedBackupRound();
|
||||
// 调用方可以任意顺序传入两份包,这里统一按 packetIndex 排序并校验必须是 1、2 两包。
|
||||
@@ -178,21 +178,25 @@ public class LmkServiceImpl implements LmkService {
|
||||
byte[] oldPin = decodeConfiguredPin("tms.mk.init-identify.old-pin-base64", masterKeyInitProperties.getOldPinBase64());
|
||||
byte[] newPin = decodeConfiguredPin("tms.mk.init-identify.new-pin-base64", masterKeyInitProperties.getNewPinBase64());
|
||||
|
||||
// 恢复顺序不能打乱:
|
||||
// 1. InitIdentify 建立恢复所需的设备认证上下文
|
||||
// 2. 先恢复 LMK 并 LoadLMK,后续 IK 和用户密钥都依赖 LMK 环境
|
||||
// 3. 再恢复两把 IK
|
||||
// 4. 最后恢复用户密钥
|
||||
pcieCryptoService.initIdentify(oldPin, newPin);
|
||||
pcieCryptoService.recoverLmkEx(Hex.decode(composeLmkHex(orderedPackets)));
|
||||
pcieCryptoService.loadLmk();
|
||||
pcieCryptoService.recoverIkComponent(IKEnums.KEY_TYPE_AUTH.getCode(), Hex.decode(composeIkHex(orderedPackets, true)));
|
||||
pcieCryptoService.recoverIkComponent(IKEnums.KEY_TYPE_DEVICE.getCode(), Hex.decode(composeIkHex(orderedPackets, false)));
|
||||
//务必先查询是否是就绪状态
|
||||
DeviceStatusResult result = pcieCryptoService.getDeviceStatus();
|
||||
log.info("device status:{}", result.getFsmState());
|
||||
pcieCryptoService.recoverUserKey(toRecoverUserKeyRequest(orderedPackets, USER_KEY_INDEX, USER_KEY_TYPE_SIGN));
|
||||
pcieCryptoService.recoverUserKey(toRecoverUserKeyRequest(orderedPackets, USER_KEY_INDEX, USER_KEY_TYPE_ENC));
|
||||
MasterKeyRecoveryRequest recoveryRequest = new MasterKeyRecoveryRequest();
|
||||
recoveryRequest.setOldPin(oldPin);
|
||||
recoveryRequest.setNewPin(newPin);
|
||||
recoveryRequest.setLmkComponent(Hex.decode(composeLmkHex(orderedPackets)));
|
||||
recoveryRequest.setAuthIkComponent(Hex.decode(composeIkHex(orderedPackets, true)));
|
||||
recoveryRequest.setDeviceIkComponent(Hex.decode(composeIkHex(orderedPackets, false)));
|
||||
recoveryRequest.setUserKeyRequests(List.of(
|
||||
toRecoverUserKeyRequest(orderedPackets, USER_KEY_INDEX, USER_KEY_TYPE_SIGN),
|
||||
toRecoverUserKeyRequest(orderedPackets, USER_KEY_INDEX, USER_KEY_TYPE_ENC)
|
||||
));
|
||||
MasterKeyRecoveryResult recoveryResult = pcieCryptoService.recoverMasterKeyMaterial(recoveryRequest);
|
||||
DeviceStatusResult deviceStatus = recoveryResult.getDeviceStatus();
|
||||
if (deviceStatus != null) {
|
||||
log.info("device status:{}", deviceStatus.getFsmState());
|
||||
}
|
||||
MasterKeyStateResult result = new MasterKeyStateResult();
|
||||
result.setStatus(true);
|
||||
result.setSeedMac(Hex.toHexString(recoveryResult.getLmkSeedMac()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user