PKCS #11
The PKCS #11 standard defines a platform-independent API to cryptographic tokens, such as hardware security modules (HSM), smart cards, and names the API itself "Cryptoki" (from "cryptographic token interface" and pronounced as "crypto-key" - but "PKCS #11" is often used to refer to the API as well as the standard that defines it).
The API defines most commonly used cryptographic object types (RSAX.509 keys, DES/Triple DES Certificates/keys, etc.) and all the functions needed to use, create/generate, modify and delete those objects.
This container relies on a PKCS#11 a library which handles the communication with the token/card. This can be a vendor specific library or an opensource one, please select the correct one depending on the type of token/card you are using.
Interface Summary
The Abstract PKCS #11 smartcard interface is summarized in the following snippet:
interface AbstractPkcs11{
certificates(slotId: number,
options?: Options,
callback?: (error: RestException, data: SafeNetCertificatesResponse) => void): Promise<SafeNetCertificatesResponse>;
info(callback?: (error: RestException, data: InfoResponse) => void): Promise<InfoResponse>;
signData(data: SafeNetSignData, callback?: (error: RestException, data: DataResponse) => void): Promise<DataResponse>;
slots(callback?: (error: RestException, data: SlotsResponse) => void): Promise<SlotsResponse>;
slotsWithTokenPresent(callback?: (error: RestException, data: SlotsResponse) => void): Promise<SlotsResponse>;
token(callback?: (error: RestException, data: TokensResponse) => void): Promise<TokensResponse>;
verifySignedData(data: Pkcs11VerifySignedData,
callback?: (error: RestException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
}
Each interface will be covered on this wiki, accompanied with example code and response objects.
Get the PKCS #11 container object
For more information on how to configure the T1C-JS client library see Client Configuration.
To set the locations of the PCKS#11 library, pass a ModuleConfig
object when initializing the client:
var moduleConfig = {
"linux": "/usr/local/lib/libeTPkcs11.so",
"mac": "/usr/local/lib/libeTPkcs11.dylib",
"win": "C:\\Windows\\System32\\eTPKCS11.dll"
}
var config = new GCLConfig("ds uri", "apikey", moduleConfig);
GCLLib.GCLClient.initialize(config, function(err, gclClient) {
// gclClient ready to use
});
Then grab a reference to the pkcs11 container:
var pkcs11 = gclClient.pkcs11();
Call a function for the PKCS #11 container:
function callback(err,data) {
if(err){console.log("Error:",JSON.stringify(err, null, ' '));}
else {console.log(JSON.stringify(data, null, ' '));}
}
gclClient.pkcs11(moduleConfig).certificates(callback);
Reading data
Info
This methods returns more information about the PKCS #11 library you are using.
gclClient.pkcs11(moduleConfig).info(callback);
An example response:
{
"data":
{
"cryptoki_version": "2.20",
"manufacturer_id": "SafeNet, Inc.",
"flags": 7,
"library_description": "eToken PKCS#11",
"library_version": "9.1"
}
"success": true
}
Slots
This methods returns the available slots on the system.
gclClient.pkcs11(moduleConfig).slots(callback);
An example response:
{
"data":
[
{
"slot_id": 0,
"description": "eToken 5100",
"flags": 7,
"hardware_version": "2.0",
"firmware_version": "0.0"
},
{
"slot_id": 1,
"description": "",
"flags": 2,
"hardware_version": "2.0",
"firmware_version": "0.0"
}
]
"success": true
}
The flags value gives more information about the slot, possible values are
Value | Description |
---|---|
0 | Empty |
1 | Token present |
2 | Removable device |
3 | Token present + removable device |
4 | Hardware slot |
5 | Token present + hardware slot |
6 | Removable device + hardware slot |
7 | Token present + removable device + hardware slot |
32 | Unknown |
Slots with tokens present
This method is similar the the slots endpoint but only returns a list of slots where a token is present.
gclClient.pkcs11(moduleConfig).slotsWithTokenPresent(callback);
An example response:
{
"data":
[
{
"slot_id": 0,
"description": "eToken 5100",
"flags": 7,
"hardware_version": "2.0",
"firmware_version": "0.0"
}
]
"success": true
}
Token
This methods returns the token information for a slot.
gclClient.pkcs11(moduleConfig).token(slot_id, callback);
An example response:
{
"data":
{
"slot_id": 1,
"label": "Token Label",
"manufacturer_id": "Gemalto",
"model": "Safenet Token e5100",
"serial_number": "1234567890",
"flags": 7,
"max_session_count": 10,
"session_count": 1,
"max_rw_session_count": 5,
"rw_session_count": 1,
"max_pin_length": 20,
"min_pin_length": 8,
"total_public_memory": 10000,
"free_public_memory": 5000,
"total_private_memory": 1000,
"free_private_memory": 50,
"hardware_version": "1",
"firmware_version": "1"
},
"success": true
}
Certificates
This methods allows you to retrieve the certificates from the PKCS #11 token.
// retrieve certificates for token in slot_id 0
gclClient.pkcs11(moduleConfig).certificates(0, { parseCerts: false }, callback);
An example callback:
function callback(err,data) {
if(err) {
console.log("Error:",JSON.stringify(err, null, ' '));
}
else {
console.log(JSON.stringify(data, null, ' '));
}
}
Response:
{
"data": [
{
"base64": "MIIFjjCCA3agAwI...rTBDdrlEWVaLrY+M+xeIctrC0WnP7u4xg==",
"id": "E8CE05618E79A79825722AE067EC0029851D860D"
},
{
"base64": "MIIFjjCCA3agAwI...rTBDdrlEWVaLrY+M+xeIctrC0WnP7u4xg==",
"id": "9F8F1CD68867526B1DF919832219B217282D2B0B"
}
],
"success": true
}
Signing data
To successfully sign data, we need the following parameters:
- Slot ID of the token to use
- Certificate ID of the signing certificate
- PIN code
- Hashed data to sign
- Hashing algorithm used
The slot id can be found using either a call to slots
, slotsWithTokenPresent
. Once the slot id is found, the certificates can be retrieved with a call to certificates
. This then returns the certificate id. Now we can combine this with the PIN code and hashed data + hashing algorithm (SHA1, SHA256, SHA384, SHA512) to create the final signData call:
signData call
Returns signed data for provided input data.
var signDataPayload = {
slot_id: 1,
cert_id: "9F8F1CD68867526B1DF919832219B217282D2B0B",
pin: "thepincodeforthetoken",
data: "hashed data"
algorithm_reference: "sha256"
}
gclClient.pkcs11(moduleConfig).signData(signDataPayload, callback);
An example response:
{
"data": "L3BWs7lvoajPg5tC9GEmlSMdXMcDkNDUVVvt+KFqbJbXkJdI3DGoM3IOeXLaeTCxKmJ33/QQApL1nEAMuHY38V41czyswfSdpnqeex3EisXKkiYHeNzt9AXeoxDtsWbGkejKqru6X4xzAy/1SnccjZ2BQB/uUwyfyyweFjbZAGCLfTzWraCxG0ud2c8itsjmsBgXSuGjLqxKIJXbtuX22gd0nc4LeZLA91sxaoNFBCEVlOgJ/oJncFylf6T/Tz9R4VOA9kSf6NB1tAMsFEsihgjZafu/rzlrOfzZw4YY/T32LKY4Y2zNnDhJAucqflZjopGadDvkkSmTvxxEJuE+Bw==",
"success": true
}
verifySignedData call
This call can be used to verify if the signed data is correct. The request is similar to signData
, but we also pass in the signed hash:
var verifyDataPayload = {
slot_id: 1,
cert_id: "9F8F1CD68867526B1DF919832219B217282D2B0B",
pin: "thepincodeforthetoken",
data: "hashed data"
algorithm_reference: "sha256",
signature: "signed hash"
}
gclClient.pkcs11(moduleConfig).verifySignedData(verifyDataPayload, callback);
An example response:
{
"data": true,
"success": true
}
Error Handling
Error Object
The functions specified are asynchronous and always need a callback function.
The callback function will reply with a data object in case of success, or with an error object in case of an error. An example callback:
function callback(err,data) {
if(err){
console.log("Error:",JSON.stringify(err, null, ' '));
}
else {
console.log(JSON.stringify(data, null, ' '));
}
}
The error object returned:
{
success: false,
description: "some error description",
code: "some error code"
}
For the error codes and description, see Status codes.