From d9794dd74835095fb3dad18b2c38723cbd8ae8e4 Mon Sep 17 00:00:00 2001 From: Federico Date: Fri, 28 Jul 2023 14:45:33 -0300 Subject: [PATCH 1/4] `SMAdapter`: add operation to encrypt PIN under PEK. --- .../src/main/java/org/jpos/security/SMAdapter.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/jpos/src/main/java/org/jpos/security/SMAdapter.java b/jpos/src/main/java/org/jpos/security/SMAdapter.java index ca2a8be15c..707f5a1334 100644 --- a/jpos/src/main/java/org/jpos/security/SMAdapter.java +++ b/jpos/src/main/java/org/jpos/security/SMAdapter.java @@ -384,7 +384,7 @@ SecureKey exportKey(SecureKey kek, SecureKey key, SecureKeySpec keySpec) * Encrypts a clear pin under LMK. * *

CAUTION: The use of clear pin presents a significant security risk - * @param pin clear pin as entered by card holder + * @param pin clear pin as entered by cardholder * @param accountNumber if extract is false then account number, including BIN and the check digit * or if parameter extract is true then 12 right-most digits of the account number, excluding the check digit * @param extract true to extract 12 right-most digits off the account number @@ -393,6 +393,18 @@ SecureKey exportKey(SecureKey kek, SecureKey key, SecureKeySpec keySpec) */ EncryptedPIN encryptPIN(String pin, String accountNumber, boolean extract) throws SMException; + /** + * Encrypts a clear PIN under PEK. + * + *

CAUTION: The use of clear PIN presents a significant security risk. + * @param pin Clear PIN as entered by cardholder. + * @param accountNumber account number, including BIN and the check digit. + * @param pek PIN encryption key. + * @return Return PIN under PEK. + * @throws SMException + */ + EncryptedPIN encryptPIN(String pin, String accountNumber, T pek) throws SMException; + /** * Decrypts an Encrypted PIN (under LMK). *

CAUTION: The use of clear pin presents a significant security risk From 2884577a8cd35895704794b6bbad169692203054 Mon Sep 17 00:00:00 2001 From: Federico Date: Fri, 28 Jul 2023 14:48:07 -0300 Subject: [PATCH 2/4] Implement new `SMAdapter` method in `BaseSMAdapter`. --- .../java/org/jpos/security/BaseSMAdapter.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/jpos/src/main/java/org/jpos/security/BaseSMAdapter.java b/jpos/src/main/java/org/jpos/security/BaseSMAdapter.java index a59fc005f5..9ffb30369c 100644 --- a/jpos/src/main/java/org/jpos/security/BaseSMAdapter.java +++ b/jpos/src/main/java/org/jpos/security/BaseSMAdapter.java @@ -309,6 +309,30 @@ public EncryptedPIN encryptPIN (String pin, String accountNumber) throws SMExcep return encryptPIN(pin, accountNumber, true); } + @Override + public EncryptedPIN encryptPIN(String pin, String accountNumber, T pek) throws SMException { + accountNumber = EncryptedPIN.extractAccountNumberPart(accountNumber); + List cmdParameters = new ArrayList<>(); + cmdParameters.add(new SimpleMsg("parameter", "clear pin", pin)); + cmdParameters.add(new SimpleMsg("parameter", "account number", accountNumber)); + cmdParameters.add(new SimpleMsg("parameter", "pin encryption Key", pek)); + LogEvent evt = new LogEvent(this, "s-m-operation"); + evt.addMessage(new SimpleMsg("command", "Encrypt clear PIN under PEK", cmdParameters)); + EncryptedPIN result = null; + try { + result = encryptPINImpl(pin, accountNumber, pek); + evt.addMessage(new SimpleMsg("result", "PIN under PEK", result)); + } + catch (Exception e) { + evt.addMessage(e); + throw e instanceof SMException ? (SMException) e : new SMException(e); + } + finally { + Logger.log(evt); + } + return result; + } + @Override public String decryptPIN (EncryptedPIN pinUnderLmk) throws SMException { List cmdParameters = new ArrayList<>(); @@ -912,6 +936,9 @@ public boolean verifydCVV(String accountNo, T imkac, String dcvv, String expDate, String serviceCode, byte[] atc, MKDMethod mkdm) throws SMException { + if (accountNo == null || accountNo.trim().length() == 0) + throw new IllegalArgumentException("Account number not set."); + List cmdParameters = new ArrayList<>(); cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo)); cmdParameters.add(new SimpleMsg("parameter", "imk-ac", imkac == null ? "" : imkac)); @@ -1578,6 +1605,19 @@ protected EncryptedPIN encryptPINImpl (String pin, String accountNumber) throws throw new SMException("Operation not supported in: " + this.getClass().getName()); } + /** + * Your SMAdapter should override this method if it has this functionality. + * + * @param pin + * @param accountNumber + * @param pek + * @return encrypted PIN under PEK. + * @throws SMException + */ + protected EncryptedPIN encryptPINImpl(String pin, String accountNumber, T pek) throws SMException { + throw new SMException("Operation not supported in: " + this.getClass().getName()); + } + /** * Your SMAdapter should override this method if it has this functionality * @param pinUnderLmk From 6a0977ab8eadda3fd914a50ee6d3e1f292a727f9 Mon Sep 17 00:00:00 2001 From: Federico Date: Fri, 28 Jul 2023 14:49:03 -0300 Subject: [PATCH 3/4] Implement new `SMAdapter` method in `JCESecurityModule`. --- .../org/jpos/security/jceadapter/JCESecurityModule.java | 8 ++++++++ .../jpos/security/jceadapter/JCESecurityModuleTest.java | 2 ++ 2 files changed, 10 insertions(+) diff --git a/jpos/src/main/java/org/jpos/security/jceadapter/JCESecurityModule.java b/jpos/src/main/java/org/jpos/security/jceadapter/JCESecurityModule.java index 0bd7bff5b5..6e025963f8 100644 --- a/jpos/src/main/java/org/jpos/security/jceadapter/JCESecurityModule.java +++ b/jpos/src/main/java/org/jpos/security/jceadapter/JCESecurityModule.java @@ -274,6 +274,14 @@ public EncryptedPIN encryptPINImpl (String pin, String accountNumber) throws SME return new EncryptedPIN(translatedPINBlock, FORMAT00, accountNumber, false); } + @Override + protected EncryptedPIN encryptPINImpl(String pin, String accountNumber, SecureDESKey pek) throws SMException { + byte[] clearPINBlock = calculatePINBlock(pin, FORMAT00, accountNumber); + Key clearPEK = decryptFromLMK(pek); + byte[] translatedPINBlock = jceHandler.encryptData(clearPINBlock, clearPEK); + return new EncryptedPIN(translatedPINBlock, FORMAT00, accountNumber, false); + } + @Override public String decryptPINImpl (EncryptedPIN pinUnderLmk) throws SMException { byte[] clearPINBlock = jceHandler.decryptData(pinUnderLmk.getPINBlock(), diff --git a/jpos/src/test/java/org/jpos/security/jceadapter/JCESecurityModuleTest.java b/jpos/src/test/java/org/jpos/security/jceadapter/JCESecurityModuleTest.java index 5570978b9e..c4943c889d 100644 --- a/jpos/src/test/java/org/jpos/security/jceadapter/JCESecurityModuleTest.java +++ b/jpos/src/test/java/org/jpos/security/jceadapter/JCESecurityModuleTest.java @@ -957,6 +957,8 @@ public void testVerifyDCVVImplException1() throws Throwable { jcesecmod.verifydCVV(accountNo, imkac, dcvv, expDate ,serviceCode, atc, MKDMethod.OPTION_A); fail("Expected SMException to be thrown"); + } catch (IllegalArgumentException ex) { + assertTrue(ex.getMessage().contains("Account")); } catch (SMException ex){ if (isJavaVersionAtMost(JAVA_13)) { assertEquals("String index out of range: -4", ex.getNested().getMessage(), "ex.getMessage()"); From b15d9a3e02c89c93b488df221c15e82a5aea714b Mon Sep 17 00:00:00 2001 From: Federico Date: Fri, 28 Jul 2023 15:08:59 -0300 Subject: [PATCH 4/4] Fix unit test. --- .../org/jpos/security/jceadapter/JCESecurityModuleTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jpos/src/test/java/org/jpos/security/jceadapter/JCESecurityModuleTest.java b/jpos/src/test/java/org/jpos/security/jceadapter/JCESecurityModuleTest.java index c4943c889d..6836ed7793 100644 --- a/jpos/src/test/java/org/jpos/security/jceadapter/JCESecurityModuleTest.java +++ b/jpos/src/test/java/org/jpos/security/jceadapter/JCESecurityModuleTest.java @@ -979,6 +979,8 @@ public void testVerifyDCVVImplException2() throws Throwable { jcesecmod.verifydCVV(accountNo, imkac, dcvv, expDate ,serviceCode, atc, MKDMethod.OPTION_A); fail("Expected SMException to be thrown"); + } catch (IllegalArgumentException ex) { + assertTrue(ex.getMessage().contains("Account")); } catch (SMException ex){ if (isJavaVersionAtMost(JAVA_14)) { assertNull(ex.getNested().getMessage(), "ex.getNested().getMessage()");