程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

Error loading PKCS keystore with multiple card readers

发布于2022-09-30 19:58     阅读(253)     评论(0)     点赞(13)     收藏(1)


I am running into a weird problem when reading CAC card, in a multi terminal setup, from Nth (Except 1st) terminal.

Environment - JDK8_u211, Destop without any card reader, Internal card reader for laptop, USB card reader, CAC\PIV card

USE-CASE Tried

  1. When the CAC card is plugged into internal slot of Laptop, everything works fine with and withou USB card terminal connected to laptop.
  2. When the CAC card is plugged into the USB reader and connected to the Desktop, everything works fine.
  3. When the CAC card is plugged into the USB reader and connected to the Laptop, the PKCS store instantiation fails, as the config uses slot=1
  4. When the CAC card is plugged into the USB reader and connected to the Laptop, if I hard code slot=4 in the config, everything works fine.

Problem: Unable to determine the correct slot to use within the config file. Somehow number of terminals is not adding up to determine the slot at runtime.

By enabling JDK debug logs, i could verify that internally "C_GetSlotList" returns 0,4 where as I have only 2 terminals, hence using index 0 or 1.

Does anyone know how to determine the correlation between terminal vs slot or is there something really wrong in the way i am trying to read the card ?

Please advise.

Sample code

    public class MultipleTerminals {

    private static String DLL_PATH = "C:\\opensc-pkcs11.dll";

    public static void main(String[] args) throws Exception {

        MyTerminal custTerminalObj = getSmartCardTerminal();
        CardTerminal terminal = custTerminalObj.getTerminal();
        Integer terminalIdx = custTerminalObj.getIndex();
        System.out.println("Using Terminal.Name: " + terminal.getName());
        System.out.println("Using Terminal.isCardPresent: " + ((CardTerminal)terminal).isCardPresent());

         if (terminal.isCardPresent()) { // duplicate check
             registerProvider(4);
             KeyStore keyStore = createKeyStore();
             printCertificate(keyStore);
         }
    }

    public static MyTerminal getSmartCardTerminal() {
        System.out.println("---------------------------------------------------");
        MyTerminal terminal = null;
        int terminalIdx = -1;
        try {
            TerminalFactory factory = TerminalFactory.getDefault();
            if (factory != null) {
                List<CardTerminal> allTerminals = factory.terminals().list();
                for(CardTerminal term : allTerminals) {
                    System.out.println("Terminal Name: " + term.getName());
                    System.out.println("isCardPresent: " + term.isCardPresent());
                    System.out.println("----------");                   
                }
                for(CardTerminal term : allTerminals) {
                    terminalIdx++;
                    if(term.isCardPresent()) {
                        terminal = new MyTerminal();
                        terminal.setIndex(terminalIdx);
                        terminal.setTerminal(term);
                        System.out.println("Using Terminal Idx: " + terminalIdx);
                    }
                }
            }
        } catch (CardException e1) {
            terminal = null;
            System.out.println("SmartCardHelper.getSmartCardTerminal --> "
                    + "Exception while accessing smart-card terminal: "
                    + e1.getMessage());
            e1.printStackTrace();
        }

        return terminal;
    }

    public static void registerProvider(Integer idx) {
        System.out.println("---------------------------------------------------");
        String ext = "attributes(*,*,*)=\n{\nCKA_TOKEN=true\nCKA_LOCAL=true\n}";
        String OPENSC_DEFAULT_PROVIDER_NAME = "PKCS#11";
        String OPENSC_PKCS11_DLL = DLL_PATH;
        String configString = "name = "
                + OPENSC_DEFAULT_PROVIDER_NAME.replace(' ', '_') + "\n"
                + "library = "
                + OPENSC_PKCS11_DLL + "\n slot = " + idx + " "
                + "\n attributes = compatibility \n" + ext;

        System.out.println("\tConfigString: " + configString);

        ByteArrayInputStream is = new ByteArrayInputStream(
                configString.getBytes(Charset.defaultCharset()));

        Provider cardSecurityProvider = new sun.security.pkcs11.SunPKCS11(
                is);

        displayProviders();
        Security.addProvider(cardSecurityProvider);
        displayProviders();
        System.out.println("==================");
    }


    public static KeyStore createKeyStore() throws KeyStoreException {
        KeyStore.CallbackHandlerProtection callbackHandler = new KeyStore.CallbackHandlerProtection(
                new PIVCardPinHandler());
        KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11", null,
                callbackHandler);
        return builder.getKeyStore();
    }

    public static void displayProviders() {
        System.out.println("---------------------------------------------------");
        Provider[] objs = Security.getProviders();
        System.out.println("Provider Count: " + objs.length);

        String type = "KeyStore";
        String algorithm="PKCS11";
        ProviderList list = Providers.getProviderList();
        Provider provider = list.getProvider("SunPKCS11-PKCS");
        System.out.println("Provider[SunPKCS11-PKCS]: " + provider);

        if(provider != null) {
            Set<Service> svcs = provider.getServices();
            System.out.println("Service count: " + svcs.size());
        }

        Service firstService = list.getService(type, algorithm);
        System.out.println("Type[KeyStore], Algo[PKCS11], Service: " + firstService);       
    }

    public static void printCertificate(KeyStore keyStore)
            throws KeyStoreException {
        for (String alias : Collections.list(keyStore.aliases())) {
            System.out.println("Alias: " + alias);
        }
    }
}


class MyTerminal{

    private Integer index;
    private CardTerminal terminal;

    public MyTerminal() {
    }

    public Integer getIndex() {
        return index;
    }
    public void setIndex(Integer index) {
        this.index = index;
    }
    public CardTerminal getTerminal() {
        return terminal;
    }
    public void setTerminal(CardTerminal terminal) {
        this.terminal = terminal;
    }   
}

* Output TestCase-1 (WORKING)*

---------------------------------------------------
Terminal Name: Alcor Micro USB Smart Card Reader 0
isCardPresent: true
----------
Terminal Name: Identive SCR33xx v2.0 USB SC Reader 0
isCardPresent: false
----------
Using Terminal Idx: 0
Using Terminal.Name: Alcor Micro USB Smart Card Reader 0
Using Terminal.isCardPresent: true
---------------------------------------------------
    ConfigString: 
name = PKCS#11
library = C:\opensc-pkcs11.dll
 slot = 0 
 attributes = compatibility 
attributes(*,*,*)=
{
CKA_TOKEN=true
CKA_LOCAL=true
}
SunPKCS11 loading ---DummyConfig-1---
sunpkcs11: Initializing PKCS#11 library C:\opensc-pkcs11.dll
Information for provider SunPKCS11-PKCS
Library info:
  cryptokiVersion: 2.20
  manufacturerID: DUMMY_VALUE                  
  flags: 0
  libraryDescription: DUMMY_VALUE      
  libraryVersion: 0.19
All slots: 0, 4
Slots with tokens: 0, 4
Slot info for slot 0:
  slotDescription: Alcor Micro USB Smart Card Reader 0                             
  manufacturerID: DUMMY_VALUE
  flags: CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT
  hardwareVersion: 0.00
  firmwareVersion: 0.00
Token info for token in slot 0:
  label: DUMMY_VALUE            
  manufacturerID: DUMMY_VALUE                          
  model: PKCS#15 emulated
  serialNumber: DUMMY_VALUE
  flags: CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED
  ulMaxSessionCount: CK_EFFECTIVELY_INFINITE
  ulSessionCount: 0
  ulMaxRwSessionCount: CK_EFFECTIVELY_INFINITE
  ulRwSessionCount: 0
  ulMaxPinLen: 8
  ulMinPinLen: 4
  ulTotalPublicMemory: CK_UNAVAILABLE_INFORMATION
  ulFreePublicMemory: CK_UNAVAILABLE_INFORMATION
  ulTotalPrivateMemory: CK_UNAVAILABLE_INFORMATION
  ulFreePrivateMemory: CK_UNAVAILABLE_INFORMATION
  hardwareVersion: 0.00
  firmwareVersion: 0.00
  utcTime: 
---------------------------------------------------
Provider Count: 10
Provider[SunPKCS11-PKCS]: null
Type[KeyStore], Algo[PKCS11], Service: null
---------------------------------------------------
Provider Count: 11
Provider[SunPKCS11-PKCS]: SunPKCS11-PKCS version 1.8
Service count: 26
Type[KeyStore], Algo[PKCS11], Service: SunPKCS11-PKCS: KeyStore.PKCS11 -> sun.security.pkcs11.P11KeyStore
  aliases: [PKCS11-PKCS]
 (KeyStore)
==================
sunpkcs11: caller passed NULL pin

* Output TestCase-3 (NOT WORKING)*

---------------------------------------------------
Terminal Name: Alcor Micro USB Smart Card Reader 0
isCardPresent: false
----------
Terminal Name: Identive SCR33xx v2.0 USB SC Reader 0
isCardPresent: true
----------
Using Terminal Idx: 1
Using Terminal.Name: Identive SCR33xx v2.0 USB SC Reader 0
Using Terminal.isCardPresent: true
---------------------------------------------------
    ConfigString: 
name = PKCS#11
library = C:\opensc-pkcs11.dll
 slot = 1 
 attributes = compatibility 
attributes(*,*,*)=
{
CKA_TOKEN=true
CKA_LOCAL=true
}
SunPKCS11 loading ---DummyConfig-1---
sunpkcs11: Initializing PKCS#11 library C:\opensc-pkcs11.dll
Information for provider SunPKCS11-PKCS
Library info:
  cryptokiVersion: 2.20
  manufacturerID: DUMMY_VALUE                  
  flags: 0
  libraryDescription: DUMMY_VALUE      
  libraryVersion: 0.19
All slots: 0, 4
Slots with tokens: 0, 4
---------------------------------------------------
Provider Count: 10
Provider[SunPKCS11-PKCS]: null
Type[KeyStore], Algo[PKCS11], Service: null
---------------------------------------------------
Provider Count: 11
Provider[SunPKCS11-PKCS]: SunPKCS11-PKCS version 1.8
Service count: 0
Type[KeyStore], Algo[PKCS11], Service: null
==================
Exception in thread "main" java.security.KeyStoreException: KeyStore instantiation failed
    at java.security.KeyStore$Builder$2.getKeyStore(KeyStore.java:1967)

Caused by: java.security.KeyStoreException: PKCS11 not found
    at java.security.KeyStore.getInstance(KeyStore.java:851)
    at java.security.KeyStore$Builder$2$1.run(KeyStore.java:1923)
    at java.security.KeyStore$Builder$2$1.run(KeyStore.java:1918)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.KeyStore$Builder$2.getKeyStore(KeyStore.java:1964)
    ... 2 more
Caused by: java.security.NoSuchAlgorithmException: PKCS11 KeyStore not available
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:159)
    at java.security.Security.getImpl(Security.java:695)
    at java.security.KeyStore.getInstance(KeyStore.java:848)
    ... 6 more

* Output TestCase-4 (WORKING)*

---------------------------------------------------
Terminal Name: Alcor Micro USB Smart Card Reader 0
isCardPresent: false
----------
Terminal Name: Identive SCR33xx v2.0 USB SC Reader 0
isCardPresent: true
----------
Using Terminal Idx: 1
Using Terminal.Name: Identive SCR33xx v2.0 USB SC Reader 0
Using Terminal.isCardPresent: true
---------------------------------------------------
    ConfigString: 
name = PKCS#11
library = C:\opensc-pkcs11.dll
 slot = 4 
 attributes = compatibility 
attributes(*,*,*)=
{
CKA_TOKEN=true
CKA_LOCAL=true
}
SunPKCS11 loading ---DummyConfig-1---
sunpkcs11: Initializing PKCS#11 library C:\opensc-pkcs11.dll
Information for provider SunPKCS11-PKCS
Library info:
  cryptokiVersion: DUMMY_VALUE
  manufacturerID: DUMMY_VALUE                  
  flags: 0
  libraryDescription: DUMMY_VALUE      
  libraryVersion: DUMMY_VALUE
All slots: 0, 4
Slots with tokens: 0, 4
Slot info for slot 4:
  slotDescription: DUMMY_VALUE                           
  manufacturerID: DUMMY_VALUE
  flags: CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT
  hardwareVersion: 0.00
  firmwareVersion: 0.00
Token info for token in slot 4:
  label: DUMMY_LABEL            
  manufacturerID: DUMMY_VALUE                          
  model: PKCS#15 emulated
  serialNumber: DUMMY_VALUE
  flags: CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED
  ulMaxSessionCount: CK_EFFECTIVELY_INFINITE
  ulSessionCount: 0
  ulMaxRwSessionCount: CK_EFFECTIVELY_INFINITE
  ulRwSessionCount: 0
  ulMaxPinLen: 8
  ulMinPinLen: 4
  ulTotalPublicMemory: CK_UNAVAILABLE_INFORMATION
  ulFreePublicMemory: CK_UNAVAILABLE_INFORMATION
  ulTotalPrivateMemory: CK_UNAVAILABLE_INFORMATION
  ulFreePrivateMemory: CK_UNAVAILABLE_INFORMATION
  hardwareVersion: 0.00
  firmwareVersion: 0.00
  utcTime: 
---------------------------------------------------
Provider Count: 10
Provider[SunPKCS11-PKCS]: null
Type[KeyStore], Algo[PKCS11], Service: null
---------------------------------------------------
Provider Count: 11
Provider[SunPKCS11-PKCS]: SunPKCS11-PKCS version 1.8
Service count: 26
Type[KeyStore], Algo[PKCS11], Service: SunPKCS11-PKCS: KeyStore.PKCS11 -> sun.security.pkcs11.P11KeyStore
  aliases: [PKCS11-PKCS]
 (KeyStore)
==================
sunpkcs11: caller passed NULL pin

解决方案


You are getting confused between slot id and slot index. They are two different attributes.

The C_GetSlotList gives you an array of slot id's not slot indexes. In your case 0 and 4 are slot id's, not slot indexes. The slot index is the index of the slot id in the array.

In your getSmartCardTerminal() method where you are identifying the terminalIdx you are identifying the index, but in your registerProvider(Integer idx) method you are mapping the index as the id, here:

OPENSC_PKCS11_DLL + "\n slot = " + idx + " "

When you are using the slot index you should be using slotListIndex and when you are using the slot id, you should be using slot.

So to fix your problem change it to:

OPENSC_PKCS11_DLL + "\n slotListIndex = " + idx + " "

Documentation here.



所属网站分类: 技术文章 > 问答

作者:黑洞官方问答小能手

链接:http://www.javaheidong.com/blog/article/526535/704376f15c4cf8ddafec/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

13 0
收藏该文
已收藏

评论内容:(最多支持255个字符)