diff --git a/README.md b/README.md index 6d6692d..25528d4 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,21 @@ mvn -q -DskipTests compile mvn -q test ``` +## PCIe Real-Card Smoke + +- Checklist: `docs/plans/2026-02-28-pcie-realcard-smoke-checklist.md` +- Script template: `scripts/pcie_realcard_smoke.sh` + +Example: + +```bash +export BASE_URL=http://127.0.0.1:8080 +export INTERNAL_TOKEN=change-me-internal-token +export ALG_SM3=1 +export ALG_SM4_ECB=1025 +./scripts/pcie_realcard_smoke.sh +``` + - CI is pinned to JDK 17 via `.github/workflows/ci.yml`. - Maven Surefire preloads Mockito javaagent to avoid dynamic self-attach failures on newer JDKs. @@ -203,4 +218,3 @@ mvn -q test - Basic auth interceptors for internal/openapi are in place. - `init/auth/device/sign/system` modules have runnable skeleton controllers and services. - `init/auth/device` modules include mapper+xml+repository-impl+DDL skeleton for TiDB. ->>>>>>> aeb6a4d (初始化项目) diff --git a/src/main/java/com/cisd/tms/integration/crypto/config/CryptoCardProperties.java b/src/main/java/com/cisd/tms/integration/crypto/config/CryptoCardProperties.java index 8ce6dcd..21f1cb0 100644 --- a/src/main/java/com/cisd/tms/integration/crypto/config/CryptoCardProperties.java +++ b/src/main/java/com/cisd/tms/integration/crypto/config/CryptoCardProperties.java @@ -14,6 +14,7 @@ public class CryptoCardProperties { private Mode mode = Mode.MOCK; private String vendorLibPath; private String vendorLibName = "swsdsdf"; + private boolean strictAlgIdValidation = true; public boolean isEnabled() { return enabled; @@ -46,4 +47,12 @@ public class CryptoCardProperties { public void setVendorLibName(String vendorLibName) { this.vendorLibName = vendorLibName; } + + public boolean isStrictAlgIdValidation() { + return strictAlgIdValidation; + } + + public void setStrictAlgIdValidation(boolean strictAlgIdValidation) { + this.strictAlgIdValidation = strictAlgIdValidation; + } } diff --git a/src/main/java/com/cisd/tms/integration/crypto/config/PcieCryptoServiceConfiguration.java b/src/main/java/com/cisd/tms/integration/crypto/config/PcieCryptoServiceConfiguration.java index 0bd607a..655206f 100644 --- a/src/main/java/com/cisd/tms/integration/crypto/config/PcieCryptoServiceConfiguration.java +++ b/src/main/java/com/cisd/tms/integration/crypto/config/PcieCryptoServiceConfiguration.java @@ -25,8 +25,11 @@ public class PcieCryptoServiceConfiguration { } if (properties.getMode() == CryptoCardProperties.Mode.JNA) { - log.info("PCIe crypto service enabled in JNA mode"); - return new JnaPcieCryptoService(sessionTemplate); + log.info( + "PCIe crypto service enabled in JNA mode, strictAlgIdValidation={}", + properties.isStrictAlgIdValidation() + ); + return new JnaPcieCryptoService(sessionTemplate, properties); } log.info("PCIe crypto service fallback to mock, current mode={}", properties.getMode()); diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/service/JnaPcieCryptoService.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/service/JnaPcieCryptoService.java index f51aef4..b66b27b 100644 --- a/src/main/java/com/cisd/tms/integration/crypto/pcie/service/JnaPcieCryptoService.java +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/service/JnaPcieCryptoService.java @@ -1,5 +1,7 @@ package com.cisd.tms.integration.crypto.pcie.service; +import com.cisd.tms.integration.crypto.config.CryptoCardProperties; +import com.cisd.tms.integration.crypto.pcie.Gm0018AlgorithmIds; import com.cisd.tms.integration.crypto.pcie.PcieCryptoException; import com.cisd.tms.integration.crypto.pcie.PcieKeyState; import com.cisd.tms.integration.crypto.pcie.PcieSessionTemplate; @@ -91,9 +93,11 @@ public class JnaPcieCryptoService implements PcieCryptoService { private static final int ECC_CIPHER_PREFIX_LENGTH = (EccRefPublicKey.MAX_LEN * 2) + 32 + Integer.BYTES; private final PcieSessionTemplate sessionTemplate; + private final boolean strictAlgIdValidation; - public JnaPcieCryptoService(PcieSessionTemplate sessionTemplate) { + public JnaPcieCryptoService(PcieSessionTemplate sessionTemplate, CryptoCardProperties properties) { this.sessionTemplate = sessionTemplate; + this.strictAlgIdValidation = properties.isStrictAlgIdValidation(); } @Override @@ -169,13 +173,18 @@ public class JnaPcieCryptoService implements PcieCryptoService { byte[] oldPinValue = requireNonEmptyBytes("oldPin", oldPin); byte[] newPinValue = requireNonEmptyBytes("newPin", newPin); - sessionTemplate.withSession("SDFE_InitIdentify", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_InitIdentify", - lib.SDFE_InitIdentify(sessionHandle, oldPinValue, oldPinValue.length, newPinValue, newPinValue.length) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_InitIdentify", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_InitIdentify", + lib.SDFE_InitIdentify(sessionHandle, oldPinValue, oldPinValue.length, newPinValue, newPinValue.length) + ); + return null; + }); + } finally { + wipe(oldPinValue); + wipe(newPinValue); + } } @Override @@ -216,20 +225,25 @@ public class JnaPcieCryptoService implements PcieCryptoService { byte[] oldPassword = requireNonEmptyBytes("oldPassword", req.getOldPassword()); byte[] newPassword = requireNonEmptyBytes("newPassword", req.getNewPassword()); - sessionTemplate.withSession("SDFE_ChangePrivateKeyAccessPassword", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_ChangePrivateKeyAccessPassword", - lib.SDFE_ChangePrivateKeyAccessPassword( - sessionHandle, - keyIndex, - oldPassword, - oldPassword.length, - newPassword, - newPassword.length - ) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_ChangePrivateKeyAccessPassword", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ChangePrivateKeyAccessPassword", + lib.SDFE_ChangePrivateKeyAccessPassword( + sessionHandle, + keyIndex, + oldPassword, + oldPassword.length, + newPassword, + newPassword.length + ) + ); + return null; + }); + } finally { + wipe(oldPassword); + wipe(newPassword); + } } @Override @@ -238,13 +252,17 @@ public class JnaPcieCryptoService implements PcieCryptoService { int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); byte[] password = requireNonEmptyBytes("password", req.getPassword()); - sessionTemplate.withSession("SDF_GetPrivateKeyAccessRight", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDF_GetPrivateKeyAccessRight", - lib.SDF_GetPrivateKeyAccessRight(sessionHandle, keyIndex, password, password.length) - ); - return null; - }); + try { + sessionTemplate.withSession("SDF_GetPrivateKeyAccessRight", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDF_GetPrivateKeyAccessRight", + lib.SDF_GetPrivateKeyAccessRight(sessionHandle, keyIndex, password, password.length) + ); + return null; + }); + } finally { + wipe(password); + } } @Override @@ -352,13 +370,17 @@ public class JnaPcieCryptoService implements PcieCryptoService { int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); byte[] keyData = requireNonEmptyBytes("keyData", req.getKeyData()); - sessionTemplate.withSession("SDFE_ImportKEK", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_ImportKEK", - lib.SDFE_ImportKEK(sessionHandle, keyIndex, keyData, keyData.length) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_ImportKEK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ImportKEK", + lib.SDFE_ImportKEK(sessionHandle, keyIndex, keyData, keyData.length) + ); + return null; + }); + } finally { + wipe(keyData); + } } @Override @@ -426,20 +448,24 @@ public class JnaPcieCryptoService implements PcieCryptoService { throw new IllegalArgumentException("storeFlag must be 0 or 1"); } - sessionTemplate.withSession("SDFE_RecoverUserKey", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_RecoverUserKey", - lib.SDFE_RecoverUserKey( - sessionHandle, - keyIndex, - keyType, - encryptedKey, - encryptedKey.length, - (byte) storeFlag - ) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_RecoverUserKey", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_RecoverUserKey", + lib.SDFE_RecoverUserKey( + sessionHandle, + keyIndex, + keyType, + encryptedKey, + encryptedKey.length, + (byte) storeFlag + ) + ); + return null; + }); + } finally { + wipe(encryptedKey); + } } @Override @@ -461,13 +487,17 @@ public class JnaPcieCryptoService implements PcieCryptoService { int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); byte[] encryptedKey = requireNonEmptyBytes("encryptedKey", req.getEncryptedKey()); - sessionTemplate.withSession("SDFE_RecoverKEK", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_RecoverKEK", - lib.SDFE_RecoverKEK(sessionHandle, keyIndex, encryptedKey, encryptedKey.length) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_RecoverKEK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_RecoverKEK", + lib.SDFE_RecoverKEK(sessionHandle, keyIndex, encryptedKey, encryptedKey.length) + ); + return null; + }); + } finally { + wipe(encryptedKey); + } } @Override @@ -506,13 +536,17 @@ public class JnaPcieCryptoService implements PcieCryptoService { public void restoreAllKey(byte[] keyImage) { byte[] safeKeyImage = requireNonEmptyBytes("keyImage", keyImage); - sessionTemplate.withSession("SDFE_RestoryKey", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_RestoryKey", - lib.SDFE_RestoryKey(sessionHandle, safeKeyImage, safeKeyImage.length) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_RestoryKey", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_RestoryKey", + lib.SDFE_RestoryKey(sessionHandle, safeKeyImage, safeKeyImage.length) + ); + return null; + }); + } finally { + wipe(safeKeyImage); + } } @Override @@ -563,10 +597,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { EnvelopedKeyBlob blob = toEnvelopedKeyBlob("envelopedKeyBlob", req.getEnvelopedKeyBlob()); sessionTemplate.withSession("SDFE_ImportEncKeyPair_ECC", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_ImportEncKeyPair_ECC", - lib.SDFE_ImportEncKeyPair_ECC(sessionHandle, keyIndex, blob) - ); + sessionTemplate.ensureSuccess("SDFE_ImportEncKeyPair_ECC", lib.SDFE_ImportEncKeyPair_ECC(sessionHandle, keyIndex, blob)); return null; }); } @@ -575,25 +606,30 @@ public class JnaPcieCryptoService implements PcieCryptoService { public void importEncryptedKeyPairRsa(ImportEncKeyPairRsaRequest request) { ImportEncKeyPairRsaRequest req = requireRequest("request", request); int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); - int symAlgId = requirePositive("symAlgId", req.getSymAlgId()); + int symAlgId = requireValidAlgId("symAlgId", req.getSymAlgId()); byte[] wrappedKey = requireNonEmptyBytes("wrappedKey", req.getWrappedKey()); byte[] encryptedData = requireNonEmptyBytes("encryptedData", req.getEncryptedData()); - sessionTemplate.withSession("SDFE_ImportEncKeyPair_RSA", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_ImportEncKeyPair_RSA", - lib.SDFE_ImportEncKeyPair_RSA( - sessionHandle, - keyIndex, - symAlgId, - wrappedKey, - wrappedKey.length, - encryptedData, - encryptedData.length - ) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_ImportEncKeyPair_RSA", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ImportEncKeyPair_RSA", + lib.SDFE_ImportEncKeyPair_RSA( + sessionHandle, + keyIndex, + symAlgId, + wrappedKey, + wrappedKey.length, + encryptedData, + encryptedData.length + ) + ); + return null; + }); + } finally { + wipe(wrappedKey); + wipe(encryptedData); + } } @Override @@ -716,7 +752,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public StandardKeyPairResult generateStandardEccKeyPair(GenerateStandardEccKeyPairRequest request) { GenerateStandardEccKeyPairRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); int keyBits = requirePositive("keyBits", req.getKeyBits()); int publicKeySize = requirePositive("publicKeyBufferSize", req.getPublicKeyBufferSize()); int privateKeySize = requirePositive("privateKeyBufferSize", req.getPrivateKeyBufferSize()); @@ -742,7 +778,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { public BackupDataResult generateKeyWithKek(GenerateKeyWithKekRequest request) { GenerateKeyWithKekRequest req = requireRequest("request", request); int keyBits = requirePositive("keyBits", req.getKeyBits()); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); int kekIndex = requireNonNegative("kekIndex", req.getKekIndex()); int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); @@ -989,7 +1025,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { public BackupDataResult generateKeyWithEpkEcc(GenerateKeyWithEpkEccRequest request) { GenerateKeyWithEpkEccRequest req = requireRequest("request", request); int keyBits = requirePositive("keyBits", req.getKeyBits()); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); EccRefPublicKey publicKeyBlob = toEccRefPublicKey("publicKeyBlob", req.getPublicKeyBlob()); int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); @@ -1067,7 +1103,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { public BackupDataResult exchangeDigitEnvelopeBaseOnEcc(ExchangeDigitEnvelopeEccRequest request) { ExchangeDigitEnvelopeEccRequest req = requireRequest("request", request); int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); EccRefPublicKey publicKeyBlob = toEccRefPublicKey("publicKeyBlob", req.getPublicKeyBlob()); EccCipher inputEnvelopeBlob = toEccCipher("inputEnvelopeBlob", req.getInputEnvelopeBlob()); int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); @@ -1213,6 +1249,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { result.setSponsorPublicKeyLength(sponsorPublicKeyBytes.length); result.setSponsorTmpPublicKey(sponsorTmpPublicKeyBytes); result.setSponsorTmpPublicKeyLength(sponsorTmpPublicKeyBytes.length); + // SDF_GenerateKeyWithECC returns a session key handle, not plaintext key bytes. result.setSessionKey(new byte[0]); result.setSessionKeyLength(0); result.setSessionKeyGenerated(keyHandleRef.getValue() != null); @@ -1247,7 +1284,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public BackupDataResult eccExternalSign(EccExternalSignRequest request) { EccExternalSignRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); EccRefPrivateKey privateKeyBlob = toEccRefPrivateKey("privateKeyBlob", req.getPrivateKeyBlob()); byte[] data = requireBytes("data", req.getData()); int signatureBufferSize = requirePositive("signatureBufferSize", req.getSignatureBufferSize()); @@ -1285,7 +1322,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public void eccExternalVerify(EccExternalVerifyRequest request) { EccExternalVerifyRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); EccRefPublicKey publicKeyBlob = toEccRefPublicKey("publicKeyBlob", req.getPublicKeyBlob()); byte[] data = requireBytes("data", req.getData()); EccSignature signature = toEccSignature("signature", req.getSignature()); @@ -1302,7 +1339,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public BackupDataResult eccExternalEncrypt(EccExternalEncryptRequest request) { EccExternalEncryptRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); EccRefPublicKey publicKeyBlob = toEccRefPublicKey("publicKeyBlob", req.getPublicKeyBlob()); byte[] data = requireBytes("data", req.getData()); int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); @@ -1324,7 +1361,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public BackupDataResult eccExternalDecrypt(EccExternalDecryptRequest request) { EccExternalDecryptRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); EccRefPrivateKey privateKeyBlob = toEccRefPrivateKey("privateKeyBlob", req.getPrivateKeyBlob()); EccCipher encryptedData = toEccCipher("encryptedData", req.getEncryptedData()); int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); @@ -1343,7 +1380,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public BackupDataResult encryptWithPlainKey(SymmetricCryptoRequest request) { SymmetricCryptoRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); byte[] key = requireNonEmptyBytes("key", req.getKey()); byte[] data = requireBytes("data", req.getData()); int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); @@ -1365,7 +1402,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public BackupDataResult decryptWithPlainKey(SymmetricCryptoRequest request) { SymmetricCryptoRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); byte[] key = requireNonEmptyBytes("key", req.getKey()); byte[] data = requireBytes("data", req.getData()); int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); @@ -1387,7 +1424,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public BackupDataResult encryptWithKekWrappedKey(SymmetricKekCryptoRequest request) { SymmetricKekCryptoRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); int kekIndex = requireNonNegative("kekIndex", req.getKekIndex()); byte[] wrappedKey = requireNonEmptyBytes("wrappedKey", req.getWrappedKey()); byte[] data = requireBytes("data", req.getData()); @@ -1410,7 +1447,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public BackupDataResult decryptWithKekWrappedKey(SymmetricKekCryptoRequest request) { SymmetricKekCryptoRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); int kekIndex = requireNonNegative("kekIndex", req.getKekIndex()); byte[] wrappedKey = requireNonEmptyBytes("wrappedKey", req.getWrappedKey()); byte[] data = requireBytes("data", req.getData()); @@ -1433,7 +1470,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public BackupDataResult calculateMacWithPlainKey(MacCalcRequest request) { MacCalcRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); byte[] key = requireNonEmptyBytes("key", req.getKey()); byte[] data = requireBytes("data", req.getData()); int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); @@ -1455,7 +1492,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public BackupDataResult digest(DigestRequest request) { DigestRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); byte[] data = requireBytes("data", req.getData()); int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); @@ -1474,30 +1511,34 @@ public class JnaPcieCryptoService implements PcieCryptoService { @Override public HmacResult hmac(HmacRequest request) { HmacRequest req = requireRequest("request", request); - int algId = requirePositive("algId", req.getAlgId()); + int algId = requireValidAlgId("algId", req.getAlgId()); byte[] key = requireNonEmptyBytes("key", req.getKey()); byte[] data = requireBytes("data", req.getData()); - return sessionTemplate.withSession("SDFE_Hmac", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess("SDFE_HmacInit", lib.SDFE_HmacInit(sessionHandle, algId, key, key.length)); - if (data.length > 0) { - sessionTemplate.ensureSuccess("SDFE_HmacUpdate", lib.SDFE_HmacUpdate(sessionHandle, data, data.length)); - } + try { + return sessionTemplate.withSession("SDFE_Hmac", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_HmacInit", lib.SDFE_HmacInit(sessionHandle, algId, key, key.length)); + if (data.length > 0) { + sessionTemplate.ensureSuccess("SDFE_HmacUpdate", lib.SDFE_HmacUpdate(sessionHandle, data, data.length)); + } - byte[] out = new byte[HMAC_MAX_LENGTH]; - IntByReference outLen = new IntByReference(out.length); - sessionTemplate.ensureSuccess("SDFE_HmacFinal", lib.SDFE_HmacFinal(sessionHandle, out, outLen)); + byte[] out = new byte[HMAC_MAX_LENGTH]; + IntByReference outLen = new IntByReference(out.length); + sessionTemplate.ensureSuccess("SDFE_HmacFinal", lib.SDFE_HmacFinal(sessionHandle, out, outLen)); - int length = outLen.getValue(); - if (length <= 0 || length > out.length) { - throw new PcieCryptoException("SDFE_HmacFinal", -1, "native returned invalid HMAC length: " + length); - } + int length = outLen.getValue(); + if (length <= 0 || length > out.length) { + throw new PcieCryptoException("SDFE_HmacFinal", -1, "native returned invalid HMAC length: " + length); + } - HmacResult result = new HmacResult(); - result.setHmacLength(length); - result.setHmac(Arrays.copyOf(out, length)); - return result; - }); + HmacResult result = new HmacResult(); + result.setHmacLength(length); + result.setHmac(Arrays.copyOf(out, length)); + return result; + }); + } finally { + wipe(key); + } } @Override @@ -1641,20 +1682,25 @@ public class JnaPcieCryptoService implements PcieCryptoService { byte[] ukeyPin = requireNonEmptyBytes("ukeyPin", req.getUkeyPin()); byte[] loginPin = requireNonEmptyBytes("loginPin", req.getLoginPin()); - sessionTemplate.withSession("SDFE_GenerateUkey", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_GenerateUkey", - lib.SDFE_GenerateUkey( - sessionHandle, - (byte) adminIndex, - ukeyPin, - ukeyPin.length, - loginPin, - loginPin.length - ) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_GenerateUkey", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_GenerateUkey", + lib.SDFE_GenerateUkey( + sessionHandle, + (byte) adminIndex, + ukeyPin, + ukeyPin.length, + loginPin, + loginPin.length + ) + ); + return null; + }); + } finally { + wipe(ukeyPin); + wipe(loginPin); + } } @Override @@ -1663,13 +1709,18 @@ public class JnaPcieCryptoService implements PcieCryptoService { byte[] ukeyPin = requireNonEmptyBytes("ukeyPin", req.getUkeyPin()); byte[] loginPin = requireNonEmptyBytes("loginPin", req.getLoginPin()); - sessionTemplate.withSession("SDFE_LoginUkey", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_LoginUkey", - lib.SDFE_LoginUkey(sessionHandle, ukeyPin, ukeyPin.length, loginPin, loginPin.length) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_LoginUkey", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_LoginUkey", + lib.SDFE_LoginUkey(sessionHandle, ukeyPin, ukeyPin.length, loginPin, loginPin.length) + ); + return null; + }); + } finally { + wipe(ukeyPin); + wipe(loginPin); + } } @Override @@ -1679,13 +1730,18 @@ public class JnaPcieCryptoService implements PcieCryptoService { byte[] oldPin = requireNonEmptyBytes("oldPin", req.getOldPin()); byte[] newPin = requireNonEmptyBytes("newPin", req.getNewPin()); - sessionTemplate.withSession("SDFE_ChangeUkeyPin", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_ChangeUkeyPin", - lib.SDFE_ChangeUkeyPin(sessionHandle, pinType, oldPin, oldPin.length, newPin, newPin.length) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_ChangeUkeyPin", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ChangeUkeyPin", + lib.SDFE_ChangeUkeyPin(sessionHandle, pinType, oldPin, oldPin.length, newPin, newPin.length) + ); + return null; + }); + } finally { + wipe(oldPin); + wipe(newPin); + } } @Override @@ -1694,23 +1750,32 @@ public class JnaPcieCryptoService implements PcieCryptoService { byte[] adminPin = requireNonEmptyBytes("adminPin", req.getAdminPin()); byte[] userPin = requireNonEmptyBytes("userPin", req.getUserPin()); - sessionTemplate.withSession("SDFE_UnlockUkey", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_UnlockUkey", - lib.SDFE_UnlockUkey(sessionHandle, adminPin, adminPin.length, userPin, userPin.length) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_UnlockUkey", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_UnlockUkey", + lib.SDFE_UnlockUkey(sessionHandle, adminPin, adminPin.length, userPin, userPin.length) + ); + return null; + }); + } finally { + wipe(adminPin); + wipe(userPin); + } } @Override public void readLmkComponent(byte[] ukeyPin) { byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin); - sessionTemplate.withSession("SDFE_ReadLMKComponent", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess("SDFE_ReadLMKComponent", lib.SDFE_ReadLMKComponent(sessionHandle, pin, pin.length)); - return null; - }); + try { + sessionTemplate.withSession("SDFE_ReadLMKComponent", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_ReadLMKComponent", lib.SDFE_ReadLMKComponent(sessionHandle, pin, pin.length)); + return null; + }); + } finally { + wipe(pin); + } } @Override @@ -1718,23 +1783,31 @@ public class JnaPcieCryptoService implements PcieCryptoService { int safeKeyType = requireNonNegative("keyType", keyType); byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin); - sessionTemplate.withSession("SDFE_ReadUkeyIKComponent", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess( - "SDFE_ReadUkeyIKComponent", - lib.SDFE_ReadUkeyIKComponent(sessionHandle, safeKeyType, pin, pin.length) - ); - return null; - }); + try { + sessionTemplate.withSession("SDFE_ReadUkeyIKComponent", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ReadUkeyIKComponent", + lib.SDFE_ReadUkeyIKComponent(sessionHandle, safeKeyType, pin, pin.length) + ); + return null; + }); + } finally { + wipe(pin); + } } @Override public void generateCertificate(byte[] ukeyPin) { byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin); - sessionTemplate.withSession("SDFE_GenerateCertificate", (lib, deviceHandle, sessionHandle) -> { - sessionTemplate.ensureSuccess("SDFE_GenerateCertificate", lib.SDFE_GenerateCertificate(sessionHandle, pin, pin.length)); - return null; - }); + try { + sessionTemplate.withSession("SDFE_GenerateCertificate", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_GenerateCertificate", lib.SDFE_GenerateCertificate(sessionHandle, pin, pin.length)); + return null; + }); + } finally { + wipe(pin); + } } @Override @@ -1835,6 +1908,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { return callback.apply(keyHandle); } finally { destroyKeyHandle(lib, sessionHandle, keyHandle); + wipe(key); } } @@ -1856,6 +1930,7 @@ public class JnaPcieCryptoService implements PcieCryptoService { return callback.apply(keyHandle); } finally { destroyKeyHandle(lib, sessionHandle, keyHandle); + wipe(wrappedKey); } } @@ -1943,6 +2018,20 @@ public class JnaPcieCryptoService implements PcieCryptoService { return value; } + private int requireValidAlgId(String name, int algId) { + int value = requirePositive(name, algId); + if (strictAlgIdValidation && !Gm0018AlgorithmIds.isSupported(value)) { + throw new IllegalArgumentException(name + " is not a supported GM/T 0018 algorithm id: 0x" + Integer.toHexString(value)); + } + return value; + } + + private static void wipe(byte[] value) { + if (value != null) { + Arrays.fill(value, (byte) 0); + } + } + private static byte[] requireNonEmptyBytes(String name, byte[] value) { if (value == null || value.length == 0) { throw new IllegalArgumentException(name + " must not be empty"); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 2997788..f780b38 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -38,3 +38,4 @@ tms: mode: ${TMS_CRYPTO_CARD_MODE:MOCK} vendor-lib-path: ${TMS_CRYPTO_VENDOR_LIB_PATH:} vendor-lib-name: ${TMS_CRYPTO_VENDOR_LIB_NAME:swsdsdf} + strict-alg-id-validation: ${TMS_CRYPTO_STRICT_ALG_ID_VALIDATION:true}