# 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:

```javascript
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](https://t1t.gitbook.io/t1c-js-guide/core/client-configuration).\
To set the locations of the PCKS#11 library, pass a `ModuleConfig` object when initializing the client:

```javascript
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:

```javascript
var pkcs11 = gclClient.pkcs11();
```

Call a function for the PKCS #11 container:

```javascript
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.

```javascript
gclClient.pkcs11(moduleConfig).info(callback);
```

An example response:

```javascript
{
    "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.

```javascript
gclClient.pkcs11(moduleConfig).slots(callback);
```

An example response:

```javascript
{
    "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.

```javascript
gclClient.pkcs11(moduleConfig).slotsWithTokenPresent(callback);
```

An example response:

```javascript
{
    "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.

```javascript
gclClient.pkcs11(moduleConfig).token(slot_id, callback);
```

An example response:

```javascript
{
    "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.

```javascript
// retrieve certificates for token in slot_id 0
gclClient.pkcs11(moduleConfig).certificates(0, { parseCerts: false }, callback);
```

An example callback:

```javascript
function callback(err,data) {
    if(err) {
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}
```

Response:

```javascript
{
  "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.

```javascript
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:

```javascript
{
    "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:

```javascript
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:

```javascript
{
    "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:

```javascript
function callback(err,data) {
    if(err){
        console.log("Error:",JSON.stringify(err, null, '  '));
    }
    else {
        console.log(JSON.stringify(data, null, '  '));
    }
}
```

The error object returned:

```javascript
{
  success: false,
  description: "some error description",
  code: "some error code"
}
```

For the error codes and description, see [Status codes](https://t1t.gitbook.io/t1c-js-guide/core/status-codes).
