The previous post was about how a smartcard – or any other token – can be accessed from java. But this requires a configuration that is fed into the PKCS#11 API. On changing environments, hardcoding this configuration is most-likely a bad idea, especially for the slot ID.
PKCS#11 Slot Retrieval
Prior to generating the PKCS#11 configuration, the slot where the token is located has to be identified. This can be done using C_GetSlotList. This method returns an array of available slots. By providing the argument true, only a list of slots with available tokens will be returned.
1 2 3 4 5 6 7 8 |
private OptionalLong getSlot() throws IOException, PKCS11Exception { PKCS11 pkcs11 = PKCS11.getInstance(libraryPath, "C_GetFunctionList", null, false); long[] slots = pkcs11.C_GetSlotList(true); if(slots.length > 0) { return OptionalLong.of(slots[0]); } return OptionalLong.empty(); } |
In this sample, libraryPath is a field holding the path to the PKCS#11 dynamic library. Furthermore, it will only return a slot if at least one token is available.
PKCS#11 Configuration Generation
Generating the configuration with a given slot is straightforward. Simply concatenate the necessary key/value pairs and transform it to an InputStream.
1 2 3 4 5 6 7 8 9 |
private InputStream createConfig(long slot) { StringBuilder buffer = new StringBuilder(); buffer.append("name = Pkcs11Accelerator\r\nlibrary = "); buffer.append(libraryPath); buffer.append("\r\nslot = "); buffer.append(slot); buffer.append("\r\n"); return new ByteArrayInputStream(buffer.toString().getBytes()); } |
Configuration with Dynamic Slot
Finally, the previous two steps have to be combined. Retrieve a slot and create a proper configuration if a token is available.
1 2 3 4 5 6 7 8 |
public Optional<InputStream> createConfig() throws IOException, PKCS11Exception { OptionalLong slot = getSlot(); if(!slot.isPresent()) { return Optional.empty(); } return Optional.of(createConfig(slot.getAsLong())); } |
This sample will return a pre-fabricated configuration to be provided to SunPKCS11. If no token is available, it an empty value will be returned.