密钥恢复优化
This commit is contained in:
parent
54cbef1ef3
commit
d1f136f8e9
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -7,7 +7,9 @@ import com.cisd.tms.integration.crypto.pcie.jna.EccRefPublicKey;
|
||||
import com.cisd.tms.integration.crypto.pcie.jna.EccSignature;
|
||||
import com.cisd.tms.integration.crypto.pcie.jna.PcieNativeLibrary;
|
||||
import com.cisd.tms.integration.crypto.pcie.jna.SdfFirmwareInfo;
|
||||
import com.cisd.tms.integration.crypto.pcie.jna.SdfeDeviceStatus;
|
||||
import com.cisd.tms.integration.crypto.pcie.jna.SdfeIkComponent;
|
||||
import com.cisd.tms.integration.crypto.pcie.jna.SdfeLmkComponent;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.DigestRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.EccInternalDecryptRequest;
|
||||
@ -23,6 +25,9 @@ import com.cisd.tms.integration.crypto.pcie.model.EccSessionKeyEncryptResult;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.FirmwareInfoResult;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.IkSignRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.IkVerifyRequest;
|
||||
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.RecoverUserKeyRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.SymmetricCryptoRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.PrivateKeyAccessRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.UserKeyDecryptRequest;
|
||||
@ -33,6 +38,7 @@ import com.sun.jna.Pointer;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -134,6 +140,72 @@ class JnaPcieCryptoServiceTest {
|
||||
Mockito.verify(sessionTemplate).withSession(Mockito.eq("SDFE_RecoverIK_EX"), Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRecoverMasterKeyMaterialWithinSingleSessionAndReturnSeedMac() {
|
||||
PcieSessionTemplate sessionTemplate = Mockito.mock(PcieSessionTemplate.class);
|
||||
CryptoCardProperties properties = new CryptoCardProperties();
|
||||
JnaPcieCryptoService service = new JnaPcieCryptoService(sessionTemplate, properties);
|
||||
Pointer session = Pointer.createConstant(2);
|
||||
byte[] seedMac = new byte[] {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
|
||||
|
||||
MasterKeyRecoveryRequest request = new MasterKeyRecoveryRequest();
|
||||
request.setOldPin("12345678".getBytes(StandardCharsets.UTF_8));
|
||||
request.setNewPin("87654321".getBytes(StandardCharsets.UTF_8));
|
||||
request.setLmkComponent(filledBytes(new SdfeLmkComponent().size(), 0x21));
|
||||
request.setAuthIkComponent(filledBytes(new SdfeIkComponent().size(), 0x31));
|
||||
request.setDeviceIkComponent(filledBytes(new SdfeIkComponent().size(), 0x41));
|
||||
RecoverUserKeyRequest signKey = new RecoverUserKeyRequest();
|
||||
signKey.setKeyIndex(1);
|
||||
signKey.setKeyType(0);
|
||||
signKey.setEncryptedKey(new byte[] {0x01, 0x02, 0x03});
|
||||
RecoverUserKeyRequest encKey = new RecoverUserKeyRequest();
|
||||
encKey.setKeyIndex(1);
|
||||
encKey.setKeyType(1);
|
||||
encKey.setEncryptedKey(new byte[] {0x11, 0x12, 0x13});
|
||||
request.setUserKeyRequests(List.of(signKey, encKey));
|
||||
|
||||
AtomicReference<PcieNativeLibrary> libRef = new AtomicReference<>();
|
||||
Mockito.when(sessionTemplate.withSession(Mockito.eq("SDFE_RecoverMasterKeyMaterial"), Mockito.any()))
|
||||
.thenAnswer(invocation -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
PcieSessionTemplate.SessionCallback<MasterKeyRecoveryResult> callback =
|
||||
(PcieSessionTemplate.SessionCallback<MasterKeyRecoveryResult>) invocation.getArgument(1);
|
||||
PcieNativeLibrary lib = Mockito.mock(PcieNativeLibrary.class);
|
||||
libRef.set(lib);
|
||||
Mockito.when(lib.SDFE_InitIdentify(Mockito.eq(session), Mockito.any(), Mockito.anyInt(), Mockito.any(), Mockito.anyInt())).thenReturn(0);
|
||||
Mockito.when(lib.SDFE_RecoverLMK_EX(Mockito.eq(session), Mockito.any(SdfeLmkComponent.class))).thenReturn(0);
|
||||
Mockito.when(lib.SDFE_LoadLMK(Mockito.eq(session))).thenReturn(0);
|
||||
Mockito.when(lib.SDFE_RecoverIK_EX(Mockito.eq(session), Mockito.eq(2), Mockito.any(SdfeIkComponent.class))).thenReturn(0);
|
||||
Mockito.when(lib.SDFE_RecoverIK_EX(Mockito.eq(session), Mockito.eq(1), Mockito.any(SdfeIkComponent.class))).thenReturn(0);
|
||||
Mockito.when(lib.SDFE_DeviceStatusGet(Mockito.eq(session), Mockito.any(SdfeDeviceStatus.class))).thenReturn(0);
|
||||
Mockito.when(lib.SDFE_RecoverUserKey(Mockito.eq(session), Mockito.eq(1), Mockito.anyInt(), Mockito.any(), Mockito.anyInt(), Mockito.anyByte())).thenReturn(0);
|
||||
Mockito.when(lib.SDFE_CheckLMK(Mockito.eq(session))).thenReturn(0);
|
||||
Mockito.when(lib.SDFE_ExportLMKSeedMAC(Mockito.eq(session), Mockito.any())).thenAnswer(exportInvocation -> {
|
||||
byte[] out = exportInvocation.getArgument(1);
|
||||
System.arraycopy(seedMac, 0, out, 0, seedMac.length);
|
||||
return 0;
|
||||
});
|
||||
return callback.apply(lib, Pointer.createConstant(1), session);
|
||||
});
|
||||
|
||||
MasterKeyRecoveryResult result = service.recoverMasterKeyMaterial(request);
|
||||
|
||||
Assertions.assertArrayEquals(seedMac, result.getLmkSeedMac());
|
||||
Assertions.assertNotNull(result.getDeviceStatus());
|
||||
Mockito.verify(sessionTemplate).withSession(Mockito.eq("SDFE_RecoverMasterKeyMaterial"), Mockito.any());
|
||||
PcieNativeLibrary lib = libRef.get();
|
||||
InOrder inOrder = Mockito.inOrder(lib);
|
||||
inOrder.verify(lib).SDFE_InitIdentify(Mockito.eq(session), Mockito.any(), Mockito.anyInt(), Mockito.any(), Mockito.anyInt());
|
||||
inOrder.verify(lib).SDFE_RecoverLMK_EX(Mockito.eq(session), Mockito.any(SdfeLmkComponent.class));
|
||||
inOrder.verify(lib).SDFE_LoadLMK(Mockito.eq(session));
|
||||
inOrder.verify(lib).SDFE_RecoverIK_EX(Mockito.eq(session), Mockito.eq(2), Mockito.any(SdfeIkComponent.class));
|
||||
inOrder.verify(lib).SDFE_RecoverIK_EX(Mockito.eq(session), Mockito.eq(1), Mockito.any(SdfeIkComponent.class));
|
||||
inOrder.verify(lib).SDFE_DeviceStatusGet(Mockito.eq(session), Mockito.any(SdfeDeviceStatus.class));
|
||||
inOrder.verify(lib, Mockito.times(2)).SDFE_RecoverUserKey(Mockito.eq(session), Mockito.eq(1), Mockito.anyInt(), Mockito.any(), Mockito.anyInt(), Mockito.anyByte());
|
||||
inOrder.verify(lib).SDFE_CheckLMK(Mockito.eq(session));
|
||||
inOrder.verify(lib).SDFE_ExportLMKSeedMAC(Mockito.eq(session), Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldExportIkPublicKeyViaSdfeExportIkPublicKey() {
|
||||
PcieSessionTemplate sessionTemplate = Mockito.mock(PcieSessionTemplate.class);
|
||||
@ -875,4 +947,10 @@ class JnaPcieCryptoServiceTest {
|
||||
Assertions.assertArrayEquals(new byte[] {0x21, 0x22, 0x23}, verifyCaptor.getValue().getData());
|
||||
Assertions.assertArrayEquals(new byte[] {0x31, 0x32}, verifyCaptor.getValue().getSignature());
|
||||
}
|
||||
|
||||
private static byte[] filledBytes(int length, int value) {
|
||||
byte[] bytes = new byte[length];
|
||||
Arrays.fill(bytes, (byte) value);
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.cisd.tms.modules.mk.controller;
|
||||
|
||||
import com.cisd.tms.common.exception.GlobalExceptionHandler;
|
||||
import com.cisd.tms.modules.mk.dto.MasterKeyStateResult;
|
||||
import com.cisd.tms.modules.mk.service.LmkService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
@ -14,6 +15,50 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
|
||||
class LmkControllerTest {
|
||||
|
||||
@Test
|
||||
void shouldReturnRecoveredMasterKeySeedMac() throws Exception {
|
||||
LmkService lmkService = Mockito.mock(LmkService.class);
|
||||
MasterKeyStateResult result = new MasterKeyStateResult();
|
||||
result.setStatus(true);
|
||||
result.setSeedMac("1112131415161718");
|
||||
Mockito.when(lmkService.recoverKeyPackets(Mockito.any())).thenReturn(result);
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new LmkController(lmkService))
|
||||
.setControllerAdvice(new GlobalExceptionHandler())
|
||||
.build();
|
||||
|
||||
mockMvc.perform(post("/api/v1/masterKey/recover")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{
|
||||
"packets": [
|
||||
{
|
||||
"packetIndex": 1,
|
||||
"lmk": {
|
||||
"lmkMac": "1112131415161718",
|
||||
"components": {
|
||||
"1": "010203040506",
|
||||
"2": "0708090a0b0c"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"packetIndex": 2,
|
||||
"lmk": {
|
||||
"lmkMac": "1112131415161718",
|
||||
"components": {
|
||||
"2": "0708090a0b0c",
|
||||
"3": "131415161718"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data.status").value(true))
|
||||
.andExpect(jsonPath("$.data.seedMac").value("1112131415161718"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectRecoverPacketsWithPacketIndexesOtherThanOneAndTwo() throws Exception {
|
||||
LmkService lmkService = Mockito.mock(LmkService.class);
|
||||
|
||||
@ -10,6 +10,8 @@ import com.cisd.tms.integration.crypto.pcie.model.EccInternalSignRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.EccInternalVerifyRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.IkSignRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.model.IkVerifyRequest;
|
||||
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.RecoverUserKeyRequest;
|
||||
import com.cisd.tms.integration.crypto.pcie.service.PcieCryptoService;
|
||||
import com.cisd.tms.modules.mk.config.MasterKeyInitProperties;
|
||||
@ -68,7 +70,7 @@ class LmkServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDestroyMasterKeyInOriginalOrder() {
|
||||
void shouldDestroyMasterKeyAfterDeletingUserKey() {
|
||||
PcieCryptoService pcieCryptoService = Mockito.mock(PcieCryptoService.class);
|
||||
MasterKeyInitProperties properties = configuredPins("MTIzNDU2Nzg=", "ODc2NTQzMjE=");
|
||||
LmkService service = new LmkServiceImpl(pcieCryptoService, properties);
|
||||
@ -76,10 +78,10 @@ class LmkServiceTest {
|
||||
service.destroyMasterKey();
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(pcieCryptoService);
|
||||
inOrder.verify(pcieCryptoService).deleteUserKey(1);
|
||||
inOrder.verify(pcieCryptoService).destroyLmk();
|
||||
inOrder.verify(pcieCryptoService).destroyIk(2);
|
||||
inOrder.verify(pcieCryptoService).destroyIk(1);
|
||||
inOrder.verify(pcieCryptoService).deleteUserKey(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -299,40 +301,38 @@ class LmkServiceTest {
|
||||
void shouldRecoverAllKeyPacketsInOrder() {
|
||||
PcieCryptoService pcieCryptoService = Mockito.mock(PcieCryptoService.class);
|
||||
MasterKeyInitProperties properties = configuredPins("MTIzNDU2Nzg=", "ODc2NTQzMjE=");
|
||||
DeviceStatusResult deviceStatus = new DeviceStatusResult();
|
||||
deviceStatus.setFsmState(0);
|
||||
Mockito.when(pcieCryptoService.getDeviceStatus()).thenReturn(deviceStatus);
|
||||
MasterKeyRecoveryResult recoveryResult = new MasterKeyRecoveryResult();
|
||||
recoveryResult.setLmkSeedMac(hex("1112131415161718"));
|
||||
recoveryResult.setDeviceStatus(new DeviceStatusResult());
|
||||
Mockito.when(pcieCryptoService.recoverMasterKeyMaterial(Mockito.any())).thenReturn(recoveryResult);
|
||||
LmkService service = new LmkServiceImpl(pcieCryptoService, properties);
|
||||
|
||||
MasterKeyBackupPacket packet1 = recoverPacketFixture(1);
|
||||
MasterKeyBackupPacket packet2 = recoverPacketFixture(2);
|
||||
|
||||
service.recoverKeyPackets(List.of(packet1, packet2));
|
||||
MasterKeyStateResult result = service.recoverKeyPackets(List.of(packet1, packet2));
|
||||
|
||||
ArgumentCaptor<byte[]> oldPinCaptor = ArgumentCaptor.forClass(byte[].class);
|
||||
ArgumentCaptor<byte[]> newPinCaptor = ArgumentCaptor.forClass(byte[].class);
|
||||
ArgumentCaptor<byte[]> lmkCaptor = ArgumentCaptor.forClass(byte[].class);
|
||||
ArgumentCaptor<byte[]> ikAuthCaptor = ArgumentCaptor.forClass(byte[].class);
|
||||
ArgumentCaptor<byte[]> ikDeviceCaptor = ArgumentCaptor.forClass(byte[].class);
|
||||
ArgumentCaptor<RecoverUserKeyRequest> recoverCaptor = ArgumentCaptor.forClass(RecoverUserKeyRequest.class);
|
||||
InOrder inOrder = Mockito.inOrder(pcieCryptoService);
|
||||
inOrder.verify(pcieCryptoService).initIdentify(oldPinCaptor.capture(), newPinCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).recoverLmkEx(lmkCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).loadLmk();
|
||||
inOrder.verify(pcieCryptoService).recoverIkComponent(Mockito.eq(2), ikAuthCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).recoverIkComponent(Mockito.eq(1), ikDeviceCaptor.capture());
|
||||
inOrder.verify(pcieCryptoService).getDeviceStatus();
|
||||
inOrder.verify(pcieCryptoService, Mockito.times(2)).recoverUserKey(recoverCaptor.capture());
|
||||
Assertions.assertArrayEquals("12345678".getBytes(StandardCharsets.UTF_8), oldPinCaptor.getValue());
|
||||
Assertions.assertArrayEquals("87654321".getBytes(StandardCharsets.UTF_8), newPinCaptor.getValue());
|
||||
ArgumentCaptor<MasterKeyRecoveryRequest> requestCaptor = ArgumentCaptor.forClass(MasterKeyRecoveryRequest.class);
|
||||
Mockito.verify(pcieCryptoService).recoverMasterKeyMaterial(requestCaptor.capture());
|
||||
MasterKeyRecoveryRequest recoveryRequest = requestCaptor.getValue();
|
||||
Assertions.assertArrayEquals("12345678".getBytes(StandardCharsets.UTF_8), recoveryRequest.getOldPin());
|
||||
Assertions.assertArrayEquals("87654321".getBytes(StandardCharsets.UTF_8), recoveryRequest.getNewPin());
|
||||
Assertions.assertArrayEquals(new byte[] {
|
||||
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06
|
||||
}, lmkCaptor.getValue());
|
||||
Assertions.assertArrayEquals(hex("1112131415162122232425262728313233344142434445464748"), ikAuthCaptor.getValue());
|
||||
Assertions.assertArrayEquals(hex("2122232425263132333435363738515253546162636465666768"), ikDeviceCaptor.getValue());
|
||||
Assertions.assertArrayEquals(hex("010203040506"), recoverCaptor.getAllValues().get(0).getEncryptedKey());
|
||||
Assertions.assertArrayEquals(hex("111213141516"), recoverCaptor.getAllValues().get(1).getEncryptedKey());
|
||||
}, recoveryRequest.getLmkComponent());
|
||||
Assertions.assertArrayEquals(hex("1112131415162122232425262728313233344142434445464748"), recoveryRequest.getAuthIkComponent());
|
||||
Assertions.assertArrayEquals(hex("2122232425263132333435363738515253546162636465666768"), recoveryRequest.getDeviceIkComponent());
|
||||
Assertions.assertEquals(2, recoveryRequest.getUserKeyRequests().size());
|
||||
Assertions.assertArrayEquals(hex("010203040506"), recoveryRequest.getUserKeyRequests().get(0).getEncryptedKey());
|
||||
Assertions.assertArrayEquals(hex("111213141516"), recoveryRequest.getUserKeyRequests().get(1).getEncryptedKey());
|
||||
Assertions.assertTrue(result.isStatus());
|
||||
Assertions.assertEquals("1112131415161718", result.getSeedMac());
|
||||
Mockito.verify(pcieCryptoService, Mockito.never()).initIdentify(Mockito.any(), Mockito.any());
|
||||
Mockito.verify(pcieCryptoService, Mockito.never()).recoverLmkEx(Mockito.any());
|
||||
Mockito.verify(pcieCryptoService, Mockito.never()).loadLmk();
|
||||
Mockito.verify(pcieCryptoService, Mockito.never()).recoverIkComponent(Mockito.anyInt(), Mockito.any());
|
||||
Mockito.verify(pcieCryptoService, Mockito.never()).recoverUserKey(Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Loading…
Reference in New Issue
Block a user